diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsFactory.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsFactory.cs new file mode 100644 index 0000000..33603cb --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsFactory.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ArrayEqualityComparer; + +public static class EqualityComparerTestsFactory +{ + private static Type ComparerType => typeof(ArrayEqualityComparer); + + [Theory] + [MemberData(nameof(Test_Factory_ExpectItemComparer_Cases))] + public static void Test_Factory_ExpectItemComparer(ArrayEqualityComparer comparer, object expectedItemComparer) + => + FactoryTestHelper.AssertItemComparerMatch(ComparerType, comparer, expectedItemComparer); + + public static IEnumerable Test_Factory_ExpectItemComparer_Cases() + { + yield return new object[] + { + ArrayEqualityComparer.Default, + EqualityComparer.Default + }; + yield return new object[] + { + ArrayEqualityComparer.Create(), + EqualityComparer.Default + }; + yield return new object[] + { + ArrayEqualityComparer.Create(null), + EqualityComparer.Default + }; + yield return new object[] + { + ArrayEqualityComparer.Create(EqualityComparer.Default), + EqualityComparer.Default + }; + yield return new object[] + { + ArrayEqualityComparer.Create(CustomEqualityComparer.Default), + CustomEqualityComparer.Default + }; + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsGeneral.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsGeneral.cs new file mode 100644 index 0000000..da39029 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsGeneral.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ArrayEqualityComparer; + +public static class EqualityComparerTestsGeneral +{ + private static readonly ArrayEqualityComparer comparer + = ArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Fact] + public static void Test_GetHashCode_SourceIsNull_ExpectZero() + { + object[]? nullObj = null; + var actual = comparer.GetHashCode(nullObj); + Assert.StrictEqual(0, actual); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsRef.cs new file mode 100644 index 0000000..d8d0c3e --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsRef.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ArrayEqualityComparer; + +public static class EqualityComparerTestsRef +{ + private static readonly ArrayEqualityComparer comparer + = ArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfArray source1, CaseParamOfArray source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfArray source1, CaseParamOfArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfArray source1, CaseParamOfArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayRef.SourceAreEqualCases(); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayRef.SourceAreNotEqualCases(); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsStruct.cs new file mode 100644 index 0000000..595de32 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ArrayEqualityComparer/EqualityComparerTestsStruct.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ArrayEqualityComparer; + +public static class EqualityComparerTestsStruct +{ + private static readonly ArrayEqualityComparer comparer + = ArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfArray source1, CaseParamOfArray source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfArray source1, CaseParamOfArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfArray source1, CaseParamOfArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayStruct.SourceAreEqualCases(); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayStruct.SourceAreNotEqualCases(); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseMapper.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseMapper.cs new file mode 100644 index 0000000..4fd5048 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseMapper.cs @@ -0,0 +1,70 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal static class CaseMapper +{ + internal static CaseParamOfIReadOnlyList[] MapToOfIReadOnlyList(params CaseParamOfArray[] @case) + => + @case.Select(param => CaseParamMapper.MapToOfIReadOnlyList(param)).ToArray(); + + internal static CaseParamOfIList[] MapToOfIList(params CaseParamOfArray[] @case) + => + @case.Select(param => CaseParamMapper.MapToOfIList(param)).ToArray(); + + internal static CaseParamOfList[] MapToOfList(params CaseParamOfArray[] @case) + { + var defaultEmpty = new List(); // the empty per case + return @case.Select(param => CaseParamMapper.MapToOfList(param, () => defaultEmpty)).ToArray(); + } + + internal static CaseParamOfImmutableArray[] MapToOfImmutableArray(params CaseParamOfArray[] @case) + => + @case.Select(param => CaseParamMapper.MapToOfImmutableArray(param)).ToArray(); + + internal static IEnumerable[]> MapToOfImmutableArrayNullable( + params CaseParamOfArray[] @case) + { + var param0 = @case[0]; + var param1 = @case[1]; + + yield return new[] + { + CaseParamMapper.MapToOfImmutableArrayNullable(param0), + CaseParamMapper.MapToOfImmutableArrayNullable(param1) + }; + + switch (param0.Items, param1.Items) + { + case (null, null): + yield return new[] + { + BuildWrappedDefaultCase(), + BuildWrappedDefaultCase() + }; + yield break; + + case (null, _): + yield return new[] + { + BuildWrappedDefaultCase(), + CaseParamMapper.MapToOfImmutableArrayNullable(param1) + }; + yield break; + + case (_, null): + yield return new[] + { + CaseParamMapper.MapToOfImmutableArrayNullable(param0), + BuildWrappedDefaultCase() + }; + yield break; + } + + static CaseParamOfImmutableArrayNullable BuildWrappedDefaultCase() + => + new(new ImmutableArray?(default)); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseParam.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseParam.cs new file mode 100644 index 0000000..1b64cbe --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseParam.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +// This classes in intended to make xUnit not to merge test cases of collections equal by value. +// There is a difference between the test cases with collections equal by value and by reference. + +public sealed record class CaseParamOfArray(T[]? Items); + +public sealed record class CaseParamOfIReadOnlyList(IReadOnlyList? Items); + +public sealed record class CaseParamOfIList(IList? Items); + +public sealed record class CaseParamOfList(List? Items); + +public sealed record class CaseParamOfImmutableArray(ImmutableArray Items); + +public sealed record class CaseParamOfImmutableArrayNullable(ImmutableArray? Items); diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseParamMapper.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseParamMapper.cs new file mode 100644 index 0000000..95ece67 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseParamMapper.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal static class CaseParamMapper +{ + internal static CaseParamOfIReadOnlyList MapToOfIReadOnlyList(CaseParamOfArray param) + => + new(InnerMapCase( + param.Items, + () => null, + () => CustomReadOnlyList.Empty, + items => new CustomReadOnlyList(items))); + + internal static CaseParamOfIList MapToOfIList(CaseParamOfArray param) + => + new(InnerMapCase( + param.Items, + () => null, + () => CustomList.Empty, + items => new CustomList(items))); + + internal static CaseParamOfList MapToOfList(CaseParamOfArray param, Func> defaultEmptySupplier) + => + new(InnerMapCase( + param.Items, + () => null, + defaultEmptySupplier, + items => new List(items))); + + internal static CaseParamOfImmutableArray MapToOfImmutableArray(CaseParamOfArray param) + => + new(InnerMapCase( + param.Items, + () => default, + () => ImmutableArray.Empty, + items => ImmutableArray.Create(items))); + + internal static CaseParamOfImmutableArrayNullable MapToOfImmutableArrayNullable(CaseParamOfArray param) + => + new(InnerMapCase( + param.Items, + () => default(ImmutableArray?), + () => ImmutableArray.Empty, + items => ImmutableArray.Create(items))); + + private static TResult? InnerMapCase( + T[]? items, + Func nullSupplier, + Func defaultEmptySupplier, + Func map) + => + items switch + { + null => nullSupplier.Invoke(), + _ when ReferenceEquals(items, EmptyArray.Value) => defaultEmptySupplier.Invoke(), + _ => map.Invoke(items) + }; +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseSourcesArrayRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseSourcesArrayRef.cs new file mode 100644 index 0000000..8d2d4d0 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseSourcesArrayRef.cs @@ -0,0 +1,172 @@ +using System.Collections.Generic; +using System.Linq; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal static class CaseSourcesArrayRef +{ + internal static IEnumerable[]> SourceAreEqualCases() + => + InnerSourceAreEqualCases().Select(InnerMapCase); + + internal static IEnumerable[]> SourceAreNotEqualCases() + => + InnerSourceAreNotEqualCases().Select(InnerMapCase); + + private static CaseParamOfArray[] InnerMapCase(string?[]?[] @case) + => + @case.Select(caseParam => new CaseParamOfArray(caseParam)).ToArray(); + + private static IEnumerable InnerSourceAreEqualCases() + { + yield return new string[]?[] + { + null, + null, + }; + yield return new[] + { + EmptyArray.Value, + EmptyArray.Value, + }; + yield return new[] + { + EmptyArray.Create(), + EmptyArray.Create(), + }; + yield return new[] + { + new[] { (string?)null }, + new[] { (string?)null }, + }; + yield return new[] + { + new[] { "1" }, + new[] { "1" }, + }; + yield return new[] + { + new[] { "1", "2" }, + new[] { "1", "2" }, + }; + yield return new[] + { + new[] { "1", "2", "3" }, + new[] { "1", "2", "3" }, + }; + yield return new[] + { + new[] { "1", "2", "3", "4" }, + new[] { "1", "2", "3", "4" }, + }; + + var array1 = new[] { "1" }; + var array2 = new[] { "1", "2" }; + var array3 = new[] { "1", "2", "3" }; + var array4 = new[] { "1", "2", "3", "4" }; + yield return new[] + { + array1, + array1, + }; + yield return new[] + { + array2, + array2, + }; + yield return new[] + { + array3, + array3, + }; + yield return new[] + { + array4, + array4, + }; + } + + private static IEnumerable InnerSourceAreNotEqualCases() + { + yield return new[] + { + null, + new[] { "1" }, + }; + yield return new[] + { + new[] { "1" }, + null, + }; + yield return new[] + { + EmptyArray.Value, + new[] { "1" }, + }; + yield return new[] + { + new[] { "1" }, + EmptyArray.Value, + }; + yield return new[] + { + new[] { "1" }, + new[] { "1", "2" }, + }; + yield return new[] + { + new[] { "1", "2" }, + new[] { "1" }, + }; + yield return new[] + { + new[] { "1", "2" }, + new[] { "1", "2", "3" }, + }; + yield return new[] + { + new[] { "1", "2", "3" }, + new[] { "1", "2" }, + }; + yield return new[] + { + new[] { "1", "2", "3" }, + new[] { "1", "2", "3", "4" }, + }; + yield return new[] + { + new[] { "1", "2", "3", "4" }, + new[] { "1", "2", "3" }, + }; + yield return new[] + { + new[] { (string?)null }, + new[] { "1" }, + }; + yield return new[] + { + new[] { "1" }, + new[] { (string?)null }, + }; + yield return new[] + { + new[] { "1", "2", "3", "3" }, + new[] { "1", "2", "3", "4" }, + }; + yield return new[] + { + new[] { "1", "2", "2", "4" }, + new[] { "1", "2", "3", "4" }, + }; + yield return new[] + { + new[] { "1", "1", "3", "4" }, + new[] { "1", "2", "3", "4" }, + }; + yield return new[] + { + new[] { "0", "2", "3", "4" }, + new[] { "1", "2", "3", "4" }, + }; + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseSourcesArrayStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseSourcesArrayStruct.cs new file mode 100644 index 0000000..fc8f38c --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CaseSourcesArrayStruct.cs @@ -0,0 +1,172 @@ +using System.Collections.Generic; +using System.Linq; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal static class CaseSourcesArrayStruct +{ + public static IEnumerable[]> SourceAreEqualCases() + => + InnerSourceAreEqualCases().Select(InnerMapCase); + + public static IEnumerable[]> SourceAreNotEqualCases() + => + InnerSourceAreNotEqualCases().Select(InnerMapCase); + + private static CaseParamOfArray[] InnerMapCase(int?[]?[] @case) + => + @case.Select(caseParam => new CaseParamOfArray(caseParam)).ToArray(); + + private static IEnumerable InnerSourceAreEqualCases() + { + yield return new int?[]?[] + { + null, + null, + }; + yield return new[] + { + EmptyArray.Value, + EmptyArray.Value, + }; + yield return new[] + { + EmptyArray.Create(), + EmptyArray.Create(), + }; + yield return new[] + { + new int?[] { null }, + new int?[] { null }, + }; + yield return new[] + { + new int?[] { 1 }, + new int?[] { 1 }, + }; + yield return new[] + { + new int?[] { 1, 2 }, + new int?[] { 1, 2 }, + }; + yield return new[] + { + new int?[] { 1, 2, 3 }, + new int?[] { 1, 2, 3 }, + }; + yield return new[] + { + new int?[] { 1, 2, 3, 4 }, + new int?[] { 1, 2, 3, 4 }, + }; + + var array1 = new int?[] { 1 }; + var array2 = new int?[] { 1, 2 }; + var array3 = new int?[] { 1, 2, 3 }; + var array4 = new int?[] { 1, 2, 3, 4 }; + yield return new[] + { + array1, + array1, + }; + yield return new[] + { + array2, + array2, + }; + yield return new[] + { + array3, + array3, + }; + yield return new[] + { + array4, + array4, + }; + } + + private static IEnumerable InnerSourceAreNotEqualCases() + { + yield return new[] + { + null, + new int?[] { 1 }, + }; + yield return new[] + { + new int?[] { 1 }, + null, + }; + yield return new[] + { + EmptyArray.Value, + new int?[] { 1 }, + }; + yield return new[] + { + new int?[] { 1 }, + EmptyArray.Value, + }; + yield return new[] + { + new int?[] { 1 }, + new int?[] { 1, 2 }, + }; + yield return new[] + { + new int?[] { 1, 2 }, + new int?[] { 1 }, + }; + yield return new[] + { + new int?[] { 1, 2 }, + new int?[] { 1, 2, 3 }, + }; + yield return new[] + { + new int?[] { 1, 2, 3 }, + new int?[] { 1, 2 }, + }; + yield return new[] + { + new int?[] { 1, 2, 3 }, + new int?[] { 1, 2, 3, 4 }, + }; + yield return new[] + { + new int?[] { 1, 2, 3, 4 }, + new int?[] { 1, 2, 3 }, + }; + yield return new[] + { + new int?[] { null }, + new int?[] { 1 }, + }; + yield return new[] + { + new int?[] { 1 }, + new int?[] { null }, + }; + yield return new[] + { + new int?[] { 1, 2, 3, 3 }, + new int?[] { 1, 2, 3, 4 }, + }; + yield return new[] + { + new int?[] { 1, 2, 2, 4 }, + new int?[] { 1, 2, 3, 4 }, + }; + yield return new[] + { + new int?[] { 1, 1, 3, 4 }, + new int?[] { 1, 2, 3, 4 }, + }; + yield return new[] + { + new int?[] { 0, 2, 3, 4 }, + new int?[] { 1, 2, 3, 4 }, + }; + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomEqualityComparer.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomEqualityComparer.cs new file mode 100644 index 0000000..778b414 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomEqualityComparer.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal sealed class CustomEqualityComparer : IEqualityComparer +{ + public bool Equals(T? x, T? y) + => + EqualityComparer.Default.Equals(x, y); + + public int GetHashCode([DisallowNull] T obj) + => + EqualityComparer.Default.GetHashCode(obj); + + public static CustomEqualityComparer Default { get; } = new(); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomList.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomList.cs new file mode 100644 index 0000000..f350a7d --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomList.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections; +using System.Collections.Generic; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal sealed class CustomList : IList +{ + private readonly T[] items; + + public CustomList(params T[] items) => this.items = items; + + public static CustomList Empty { get; } = new(); + + public bool IsReadOnly => true; + + public int Count => items.Length; + + public T this[int index] + { + get => items[index]; + set => throw new NotImplementedException(); + } + + public IEnumerator GetEnumerator() + { + foreach (var item in items) yield return item; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + int IList.IndexOf(T item) + => + throw new NotImplementedException(); + + void IList.Insert(int index, T item) + => + throw new NotImplementedException(); + + void IList.RemoveAt(int index) + => + throw new NotImplementedException(); + + void ICollection.Add(T item) + => + throw new NotImplementedException(); + + void ICollection.Clear() + => + throw new NotImplementedException(); + + bool ICollection.Contains(T item) + => + throw new NotImplementedException(); + + void ICollection.CopyTo(T[] array, int arrayIndex) + => + throw new NotImplementedException(); + + bool ICollection.Remove(T item) + => + throw new NotImplementedException(); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomReadOnlyList.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomReadOnlyList.cs new file mode 100644 index 0000000..51c56c6 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/CustomReadOnlyList.cs @@ -0,0 +1,24 @@ +using System.Collections; +using System.Collections.Generic; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal sealed class CustomReadOnlyList : IReadOnlyList +{ + private readonly T[] items; + + public CustomReadOnlyList(params T[] items) => this.items = items; + + public static CustomReadOnlyList Empty { get; } = new(); + + public int Count => items.Length; + + public T this[int index] => items[index]; + + public IEnumerator GetEnumerator() + { + foreach (var item in items) yield return item; + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/EmptyArray.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/EmptyArray.cs new file mode 100644 index 0000000..2e74923 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/EmptyArray.cs @@ -0,0 +1,15 @@ +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal static class EmptyArray +{ +#pragma warning disable CA1825 // Avoid zero-length array allocations + internal static T[] Create() => new T[0]; +#pragma warning restore CA1825 // Avoid zero-length array allocations + + internal static T[] Value => InnerEmpty.Value; + + private static class InnerEmpty + { + internal static readonly T[] Value = Create(); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/FactoryTestHelper.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/FactoryTestHelper.cs new file mode 100644 index 0000000..ead3f37 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/FactoryTestHelper.cs @@ -0,0 +1,22 @@ +using System; +using System.Reflection; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests; + +internal static class FactoryTestHelper +{ + internal static void AssertItemComparerMatch( + Type type, + TCollectionComparer collectionComparer, + object itemComparerMatch) + { + var field = type.GetField("comparer", BindingFlags.Instance | BindingFlags.NonPublic); + + Assert.NotNull(field); + Assert.True(field.IsPrivate); + + var itemComparer = field.GetValue(collectionComparer); + Assert.True(ReferenceEquals(itemComparer, itemComparerMatch)); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer/EqualityComparerTestsFactory.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer/EqualityComparerTestsFactory.cs new file mode 100644 index 0000000..cffb9f7 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer/EqualityComparerTestsFactory.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer; + +public static class EqualityComparerTestsFactory +{ + private static Type ComparerType => typeof(ImmutableArrayEqualityComparer); + + [Theory] + [MemberData(nameof(Test_Factory_ExpectItemComparer_Cases))] + public static void Test_Factory_ExpectItemComparer(ImmutableArrayEqualityComparer comparer, object expectedItemComparer) + => + FactoryTestHelper.AssertItemComparerMatch(ComparerType, comparer, expectedItemComparer); + + public static IEnumerable Test_Factory_ExpectItemComparer_Cases() + { + yield return new object[] + { + ImmutableArrayEqualityComparer.Default, + EqualityComparer.Default + }; + yield return new object[] + { + ImmutableArrayEqualityComparer.Create(), + EqualityComparer.Default + }; + yield return new object[] + { + ImmutableArrayEqualityComparer.Create(null), + EqualityComparer.Default + }; + yield return new object[] + { + ImmutableArrayEqualityComparer.Create(EqualityComparer.Default), + EqualityComparer.Default + }; + yield return new object[] + { + ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default), + CustomEqualityComparer.Default + }; + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsGeneral.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsGeneral.cs new file mode 100644 index 0000000..680512d --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsGeneral.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer_Normal; + +public static class EqualityComparerTestsGeneral +{ + private static readonly ImmutableArrayEqualityComparer comparer + = ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Fact] + public static void Test_GetHashCode_SourceIsDefault_ExpectZero() + { + ImmutableArray defaultObj = default; + var actual = comparer.GetHashCode(defaultObj); + Assert.StrictEqual(0, actual); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsRef.cs new file mode 100644 index 0000000..f869b7b --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsRef.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer_Normal; + +public static class EqualityComparerTestsRef +{ + private static readonly ImmutableArrayEqualityComparer comparer + = ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfImmutableArray source1, CaseParamOfImmutableArray source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfImmutableArray source1, CaseParamOfImmutableArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfImmutableArray source1, CaseParamOfImmutableArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayRef.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfImmutableArray(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayRef.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfImmutableArray(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsStruct.cs new file mode 100644 index 0000000..5c927e2 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Normal/EqualityComparerTestsStruct.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer_Normal; + +public static class EqualityComparerTestsStruct +{ + private static readonly ImmutableArrayEqualityComparer comparer + = ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfImmutableArray source1, CaseParamOfImmutableArray source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfImmutableArray source1, CaseParamOfImmutableArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfImmutableArray source1, CaseParamOfImmutableArray source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayStruct.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfImmutableArray(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayStruct.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfImmutableArray(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsGeneral.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsGeneral.cs new file mode 100644 index 0000000..7ef86ff --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsGeneral.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer_Nullable; + +public static class EqualityComparerTestsGeneral +{ + private static readonly ImmutableArrayEqualityComparer comparer + = ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Fact] + public static void Test_GetHashCode_SourceIsNull_ExpectZero() + { + ImmutableArray? nullObj = default; + var actual = comparer.GetHashCode(nullObj); + Assert.StrictEqual(0, actual); + } + + [Fact] + public static void Test_GetHashCode_SourceIsWrappedDefault_ExpectZero() + { + var wrappedDefaultObj = new ImmutableArray?(default); + var actual = comparer.GetHashCode(wrappedDefaultObj); + Assert.StrictEqual(0, actual); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsRef.cs new file mode 100644 index 0000000..1735de9 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsRef.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer_Nullable; + +public static class EqualityComparerTestsRef +{ + private static readonly ImmutableArrayEqualityComparer comparer + = ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfImmutableArrayNullable source1, CaseParamOfImmutableArrayNullable source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfImmutableArrayNullable source1, CaseParamOfImmutableArrayNullable source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfImmutableArrayNullable source1, CaseParamOfImmutableArrayNullable source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayRef.SourceAreEqualCases() + .SelectMany(@case => CaseMapper.MapToOfImmutableArrayNullable(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayRef.SourceAreNotEqualCases() + .SelectMany(@case => CaseMapper.MapToOfImmutableArrayNullable(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsStruct.cs new file mode 100644 index 0000000..3cf6d71 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ImmutableArrayEqualityComparer_Nullable/EqualityComparerTestsStruct.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ImmutableArrayEqualityComparer_Nullable; + +public static class EqualityComparerTestsStruct +{ + private static readonly ImmutableArrayEqualityComparer comparer + = ImmutableArrayEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfImmutableArrayNullable source1, CaseParamOfImmutableArrayNullable source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfImmutableArrayNullable source1, CaseParamOfImmutableArrayNullable source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfImmutableArrayNullable source1, CaseParamOfImmutableArrayNullable source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayStruct.SourceAreEqualCases() + .SelectMany(@case => CaseMapper.MapToOfImmutableArrayNullable(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayStruct.SourceAreNotEqualCases() + .SelectMany(@case => CaseMapper.MapToOfImmutableArrayNullable(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer/EqualityComparerTestsFactory.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer/EqualityComparerTestsFactory.cs new file mode 100644 index 0000000..b852f4e --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer/EqualityComparerTestsFactory.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer; + +public static class EqualityComparerTestsFactory +{ + private static Type ComparerType => typeof(ListEqualityComparer); + + [Theory] + [MemberData(nameof(Test_Factory_ExpectItemComparer_Cases))] + public static void Test_Factory_ExpectItemComparer(ListEqualityComparer comparer, object expectedItemComparer) + => + FactoryTestHelper.AssertItemComparerMatch(ComparerType, comparer, expectedItemComparer); + + public static IEnumerable Test_Factory_ExpectItemComparer_Cases() + { + yield return new object[] + { + ListEqualityComparer.Default, + EqualityComparer.Default + }; + yield return new object[] + { + ListEqualityComparer.Create(), + EqualityComparer.Default + }; + yield return new object[] + { + ListEqualityComparer.Create(null), + EqualityComparer.Default + }; + yield return new object[] + { + ListEqualityComparer.Create(EqualityComparer.Default), + EqualityComparer.Default + }; + yield return new object[] + { + ListEqualityComparer.Create(CustomEqualityComparer.Default), + CustomEqualityComparer.Default + }; + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsGeneral.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsGeneral.cs new file mode 100644 index 0000000..10f3212 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsGeneral.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer_IList; + +public static class EqualityComparerTestsGeneral +{ + private static readonly ListEqualityComparer comparer + = ListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Fact] + public static void Test_GetHashCode_SourceIsNull_ExpectZero() + { + IList? nullObj = null; + var actual = comparer.GetHashCode(nullObj); + Assert.StrictEqual(0, actual); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsRef.cs new file mode 100644 index 0000000..9d0a0fc --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsRef.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer_IList; + +public static class EqualityComparerTestsRef +{ + private static readonly ListEqualityComparer comparer + = ListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfIList source1, CaseParamOfIList source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfIList source1, CaseParamOfIList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfIList source1, CaseParamOfIList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayRef.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfIList(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayRef.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfIList(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsStruct.cs new file mode 100644 index 0000000..feb5e12 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_IList/EqualityComparerTestsStruct.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer_IList; + +public static class EqualityComparerTestsStruct +{ + private static readonly ListEqualityComparer comparer + = ListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfIList source1, CaseParamOfIList source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfIList source1, CaseParamOfIList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfIList source1, CaseParamOfIList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayStruct.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfIList(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayStruct.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfIList(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsGeneral.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsGeneral.cs new file mode 100644 index 0000000..275f239 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsGeneral.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer_List; + +public static class EqualityComparerTestsGeneral +{ + private static readonly ListEqualityComparer comparer + = ListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Fact] + public static void Test_GetHashCode_SourceIsNull_ExpectZero() + { + List? nullObj = null; + var actual = comparer.GetHashCode(nullObj); + Assert.StrictEqual(0, actual); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsRef.cs new file mode 100644 index 0000000..69b1ad3 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsRef.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer_List; + +public static class EqualityComparerTestsRef +{ + private static readonly ListEqualityComparer comparer + = ListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfList source1, CaseParamOfList source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfList source1, CaseParamOfList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfList source1, CaseParamOfList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayRef.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfList(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayRef.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfList(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsStruct.cs new file mode 100644 index 0000000..ab28243 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ListEqualityComparer_List/EqualityComparerTestsStruct.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ListEqualityComparer_List; + +public static class EqualityComparerTestsStruct +{ + private static readonly ListEqualityComparer comparer + = ListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfList source1, CaseParamOfList source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfList source1, CaseParamOfList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfList source1, CaseParamOfList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayStruct.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfList(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayStruct.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfList(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsFactory.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsFactory.cs new file mode 100644 index 0000000..88c85a0 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsFactory.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ReadOnlyListEqualityComparer; + +public static class EqualityComparerTestsFactory +{ + private static Type ComparerType => typeof(ReadOnlyListEqualityComparer); + + [Theory] + [MemberData(nameof(Test_Factory_ExpectItemComparer_Cases))] + public static void Test_Factory_ExpectItemComparer(ReadOnlyListEqualityComparer comparer, object expectedItemComparer) + => + FactoryTestHelper.AssertItemComparerMatch(ComparerType, comparer, expectedItemComparer); + + public static IEnumerable Test_Factory_ExpectItemComparer_Cases() + { + yield return new object[] + { + ReadOnlyListEqualityComparer.Default, + EqualityComparer.Default + }; + yield return new object[] + { + ReadOnlyListEqualityComparer.Create(), + EqualityComparer.Default + }; + yield return new object[] + { + ReadOnlyListEqualityComparer.Create(null), + EqualityComparer.Default + }; + yield return new object[] + { + ReadOnlyListEqualityComparer.Create(EqualityComparer.Default), + EqualityComparer.Default + }; + yield return new object[] + { + ReadOnlyListEqualityComparer.Create(CustomEqualityComparer.Default), + CustomEqualityComparer.Default + }; + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsGeneral.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsGeneral.cs new file mode 100644 index 0000000..e8fb21a --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsGeneral.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ReadOnlyListEqualityComparer; + +public static class EqualityComparerTestsGeneral +{ + private static readonly ReadOnlyListEqualityComparer comparer + = ReadOnlyListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Fact] + public static void Test_GetHashCode_SourceIsNull_ExpectZero() + { + IReadOnlyList? nullObj = null; + var actual = comparer.GetHashCode(nullObj); + Assert.StrictEqual(0, actual); + } +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsRef.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsRef.cs new file mode 100644 index 0000000..810fc62 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsRef.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ReadOnlyListEqualityComparer; + +public static class EqualityComparerTestsRef +{ + private static readonly ReadOnlyListEqualityComparer comparer + = ReadOnlyListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfIReadOnlyList source1, CaseParamOfIReadOnlyList source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfIReadOnlyList source1, CaseParamOfIReadOnlyList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfIReadOnlyList source1, CaseParamOfIReadOnlyList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayRef.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfIReadOnlyList(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayRef.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfIReadOnlyList(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsStruct.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsStruct.cs new file mode 100644 index 0000000..d110b07 --- /dev/null +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers.Tests/ReadOnlyListEqualityComparer/EqualityComparerTestsStruct.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.Linq; +using Xunit; + +namespace PrimeFuncPack.Collections.Generic.EqualityComparers.Tests.ReadOnlyListEqualityComparer; + +public static class EqualityComparerTestsStruct +{ + private static readonly ReadOnlyListEqualityComparer comparer + = ReadOnlyListEqualityComparer.Create(CustomEqualityComparer.Default); + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_GetHashCode_SourceAreEqual_ExpectHashCodesAreEqual(CaseParamOfIReadOnlyList source1, CaseParamOfIReadOnlyList source2) + { + var hashCode1 = comparer.GetHashCode(source1.Items); + var hashCode2 = comparer.GetHashCode(source2.Items); + Assert.StrictEqual(hashCode1, hashCode2); + } + + [Theory] + [MemberData(nameof(SourceAreEqualCases))] + public static void Test_Equals_SourceAreEqual_ExpectTrue(CaseParamOfIReadOnlyList source1, CaseParamOfIReadOnlyList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.True(actualEquals); + } + + [Theory] + [MemberData(nameof(SourceAreNotEqualCases))] + public static void Test_Equals_SourceAreNotEqual_ExpectTrue(CaseParamOfIReadOnlyList source1, CaseParamOfIReadOnlyList source2) + { + var actualEquals = comparer.Equals(source1.Items, source2.Items); + Assert.False(actualEquals); + } + + public static IEnumerable SourceAreEqualCases() + => + CaseSourcesArrayStruct.SourceAreEqualCases() + .Select(@case => CaseMapper.MapToOfIReadOnlyList(@case)); + + public static IEnumerable SourceAreNotEqualCases() + => + CaseSourcesArrayStruct.SourceAreNotEqualCases() + .Select(@case => CaseMapper.MapToOfIReadOnlyList(@case)); +} diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/Collections.Generic.EqualityComparers.csproj b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/Collections.Generic.EqualityComparers.csproj index ab1a90e..f8b2fbd 100644 --- a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/Collections.Generic.EqualityComparers.csproj +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/Collections.Generic.EqualityComparers.csproj @@ -16,8 +16,8 @@ Copyright © 2022-2023 Andrei Sergeev, Pavel Moskovoy PrimeFuncPack Generic Collections.EqualityComparers is a core library for .NET consisting of collection value equality comparers. System.Collections.Generic - EarlyFuncPack.Collections.Generic.EqualityComparers - 0.99.0 + PrimeFuncPack.Collections.Generic.EqualityComparers + 1.0.0 diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ArrayEqualityComparer.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ArrayEqualityComparer.cs index 011f8e3..115177c 100644 --- a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ArrayEqualityComparer.cs +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ArrayEqualityComparer.cs @@ -51,7 +51,7 @@ public bool Equals(T[]? x, T[]? y) public int GetHashCode(T[]? obj) { - if (obj is null) // Return zero instead of throwing ArgumentNullException + if (obj is null) { return default; } diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ImmutableArrayEqualityComparer.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ImmutableArrayEqualityComparer.cs index 9861804..25673d6 100644 --- a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ImmutableArrayEqualityComparer.cs +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ImmutableArrayEqualityComparer.cs @@ -29,7 +29,7 @@ public bool Equals(ImmutableArray x, ImmutableArray y) return true; } - if (x.IsDefault || y.IsDefault) // The default means null + if (x.IsDefault || y.IsDefault) // The null case { return false; } @@ -53,7 +53,7 @@ public bool Equals(ImmutableArray x, ImmutableArray y) public int GetHashCode(ImmutableArray obj) { - if (obj.IsDefault) // Return zero instead of throwing ArgumentNullException + if (obj.IsDefault) // The null case { return default; } @@ -71,11 +71,11 @@ public int GetHashCode(ImmutableArray obj) public bool Equals(ImmutableArray? x, ImmutableArray? y) => - Equals(x ?? default, y ?? default); // The default means null + Equals(x.GetValueOrDefault(), y.GetValueOrDefault()); public int GetHashCode(ImmutableArray? obj) => - GetHashCode(obj ?? default); // The default means null + GetHashCode(obj.GetValueOrDefault()); private static class InnerDefault { diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ListEqualityComparer.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ListEqualityComparer.cs index d83dc4a..23dbbc8 100644 --- a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ListEqualityComparer.cs +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ListEqualityComparer.cs @@ -51,7 +51,7 @@ public bool Equals(IList? x, IList? y) public int GetHashCode(IList? obj) { - if (obj is null) // Return zero instead of throwing ArgumentNullException + if (obj is null) { return default; } diff --git a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ReadOnlyListEqualityComparer.cs b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ReadOnlyListEqualityComparer.cs index e9e8c40..b5e2c3f 100644 --- a/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ReadOnlyListEqualityComparer.cs +++ b/src/collections-generic-equalitycomparers/Collections.Generic.EqualityComparers/EqualityComparers/ReadOnlyListEqualityComparer.cs @@ -51,7 +51,7 @@ public bool Equals(IReadOnlyList? x, IReadOnlyList? y) public int GetHashCode(IReadOnlyList? obj) { - if (obj is null) // Return zero instead of throwing ArgumentNullException + if (obj is null) { return default; } diff --git a/src/collections-generic/Collections.Generic/Collections.Generic.csproj b/src/collections-generic/Collections.Generic/Collections.Generic.csproj index d07d1a8..4ee9725 100644 --- a/src/collections-generic/Collections.Generic/Collections.Generic.csproj +++ b/src/collections-generic/Collections.Generic/Collections.Generic.csproj @@ -16,8 +16,8 @@ Copyright © 2022-2023 Andrei Sergeev, Pavel Moskovoy PrimeFuncPack Generic Collections is a core library pack for .NET consisting of collection extensions such as collection value equality comparers. System.Collections.Generic - EarlyFuncPack.Collections.Generic - 0.99.0 + PrimeFuncPack.Collections.Generic + 1.0.0 @@ -32,7 +32,7 @@ - +