From 81d9acf614a5024c7e37646a8d16adeec902b1f7 Mon Sep 17 00:00:00 2001 From: Antao Almada Date: Sun, 21 Mar 2021 01:13:33 +0000 Subject: [PATCH 1/2] Refactor enumerables unit testing --- .../AsValueEnumerable'1.Enumerable.Tests.cs | 43 ++-- ...ueEnumerable'1.ReadOnlyCollection.Tests.cs | 62 +++--- ...alueEnumerable'2.ValueEnumerable.Tests.cs} | 25 ++- ...erable'2.ValueReadOnlyCollection.Tests.cs} | 48 ++--- .../AsValueEnumerable'6.Enumerable.Tests.cs | 152 ++++++++------- ...ueEnumerable'6.ReadOnlyCollection.Tests.cs | 184 +++++++++--------- ...ValueEnumerable'6.ValueEnumerable.Tests.cs | 17 +- ...merable'6.ValueReadOnlyCollection.Tests.cs | 40 ++-- .../AsValueEnumerable.ArraySegment.Tests.cs | 90 ++------- .../AsValueEnumerable.ReadOnlyList.Tests.cs | 111 +---------- .../AsValueEnumerable.ReadOnlyMemory.Tests.cs | 88 ++------- .../AsValueEnumerable.ReadOnlySpan.Tests.cs | 69 +------ ...ValueEnumerable.ValueReadOnlyList.Tests.cs | 103 +--------- .../Where/Where.ArraySegment.Tests.cs | 6 +- .../WhereAt/WhereAt.ArraySegment.Tests.cs | 4 +- .../WhereSelect.ArraySegment.Tests.cs | 4 +- .../NetFabric.Hyperlinq.UnitTests.csproj | 5 + .../Skip/Skip.ValueEnumerable.Tests.cs | 63 ++---- .../Select/Select.ArraySegment.Tests.cs | 4 +- .../SelectAt/SelectAt.ArraySegment.Tests.cs | 4 +- .../Distinct/Distinct.ArraySegment.Tests.cs | 91 ++------- .../Distinct.AsyncValueEnumerable.Tests.cs | 4 +- .../Distinct/Distinct.ReadOnlyMemory.Tests.cs | 82 ++------ .../Distinct/Distinct.ReadOnlySpan.Tests.cs | 4 +- .../Distinct.ValueEnumerable.Tests.cs | 83 ++------ .../Distinct.ValueReadOnlyList.Tests.cs | 71 +++++++ .../Utils/ExpressionEx.cs | 140 +++++++++++++ .../Utils/GetOperationCallExpression.cs | 123 ++++++++++++ ...ValueEnumerableTestsBase'1.Partitioning.cs | 90 +++++++++ .../ValueEnumerableTestsBase'1.cs | 14 ++ .../ValueEnumerableTestsBase'4.Aggregation.cs | 34 ++++ .../ValueEnumerableTestsBase'4.Conversion.cs | 156 +++++++++++++++ .../ValueEnumerableTestsBase'4.Element.cs | 61 ++++++ ...ValueEnumerableTestsBase'4.Partitioning.cs | 61 ++++++ .../ValueEnumerableTestsBase'4.cs | 42 ++++ .../AsValueEnumerable'1.Enumerable.cs | 4 +- .../AsValueEnumerable'1.ReadOnlyCollection.cs | 4 +- ...=> AsValueEnumerable'2.ValueEnumerable.cs} | 4 +- ...ueEnumerable'2.ValueReadOnlyCollection.cs} | 50 ++--- .../AsValueEnumerable'6.Enumerable.cs | 4 +- .../AsValueEnumerable'6.ReadOnlyCollection.cs | 4 +- .../AsValueEnumerable'6.ValueEnumerable.cs | 4 +- ...lueEnumerable'6.ValueReadOnlyCollection.cs | 4 +- .../AsValueEnumerable.ArraySegment.cs | 4 +- .../AsValueEnumerable.ReadOnlyList.cs | 19 +- .../AsValueEnumerable.ReadOnlyMemory.cs | 6 +- .../AsValueEnumerable.ReadOnlySpan.cs | 6 +- .../ToList/ToList.ValueReadOnlyCollection.cs | 10 +- .../Generation/AsyncValueEnumerable/Range.cs | 4 +- .../Generation/AsyncValueEnumerable/Repeat.cs | 4 +- .../Generation/ValueEnumerable/Range.cs | 4 +- .../Generation/ValueEnumerable/Repeat.cs | 4 +- .../Skip/Skip.AsyncValueEnumerable.cs | 64 ++++++ .../Partitioning/Skip/Skip.ValueEnumerable.cs | 64 ++++++ .../SkipTake/SkipTake.AsyncValueEnumerable.cs | 71 ++++++- .../SkipTake/SkipTake.ValueEnumerable.cs | 70 ++++++- .../SkipTake.ValueReadOnlyCollection.cs | 78 +++++++- .../Take/Take.AsyncValueEnumerable.cs | 64 ++++++ .../Partitioning/Take/Take.ValueEnumerable.cs | 64 ++++++ .../Contains/Contains.ReadOnlySpan.cs | 2 +- .../Contains/Contains.ValueEnumerable.cs | 2 +- .../Set/Distinct/Distinct.ArraySegment.cs | 4 + .../Distinct/Distinct.AsyncValueEnumerable.cs | 4 + .../Set/Distinct/Distinct.ReadOnlyMemory.cs | 4 + .../Set/Distinct/Distinct.ReadOnlySpan.cs | 4 + .../Set/Distinct/Distinct.ValueEnumerable.cs | 4 + .../Utils/{Utils.SkipTake.cs => Partition.cs} | 2 +- 67 files changed, 1755 insertions(+), 1063 deletions(-) rename NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/{AsValueEnumerable'1.ValueEnumerable.Tests.cs => AsValueEnumerable'2.ValueEnumerable.Tests.cs} (56%) rename NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/{AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs => AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs} (54%) create mode 100644 NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/Utils/ExpressionEx.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/Utils/GetOperationCallExpression.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs rename NetFabric.Hyperlinq/Conversion/AsValueEnumerable/{AsValueEnumerable'1.ValueEnumerable.cs => AsValueEnumerable'2.ValueEnumerable.cs} (97%) rename NetFabric.Hyperlinq/Conversion/AsValueEnumerable/{AsValueEnumerable'1.ValueReadOnlyCollection.cs => AsValueEnumerable'2.ValueReadOnlyCollection.cs} (79%) rename NetFabric.Hyperlinq/Utils/{Utils.SkipTake.cs => Partition.cs} (96%) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs index 3a7e9a632..4fe6a804f 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs @@ -1,31 +1,28 @@ -using System.Linq; using NetFabric.Assertive; using Xunit; +using System.Linq; +using System.Collections.Generic; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Enumerable { - public partial class EnumerableTests + public partial class Tests { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + [Fact] + public void AsValueEnumerable1_Enumerator_With_ValidData_Must_Succeed() { // Arrange var wrapped = Wrap - .AsEnumerable(source); + .AsEnumerable(System.Array.Empty()); // Act var result = wrapped - .AsValueEnumerable(); + .AsValueEnumerable(); // Assert _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source); + .BeOfType>(); } - + [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -37,15 +34,27 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) .AsEnumerable(source); var expected = source .Sum(); - + // Act var result = wrapped - .AsValueEnumerable() + .AsValueEnumerable() .Sum(); - + // Assert _ = result.Must() .BeEqualTo(expected); - } + } } + + public class ValueEnumerableTests1 + : ValueEnumerableTestsBase< + EnumerableExtensions.ValueEnumerable, + ValueEnumerableExtensions.SkipEnumerable, ValueEnumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, ValueEnumerator, int>> + { + public ValueEnumerableTests1() + : base(array => Wrap.AsEnumerable(array).AsValueEnumerable()) + {} + } + } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs index 5550c1295..f6f98f9ac 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs @@ -1,53 +1,27 @@ -using System.Linq; using NetFabric.Assertive; +using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ReadOnlyCollection { - public partial class ReadOnlyCollectionTests + public partial class Tests { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - - // Act - var result = wrapped - .AsValueEnumerable(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source) + [Fact] + public void AsValueEnumerable1_Enumerator_With_ValidData_Must_Succeed() { // Arrange var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = source - .Count(); + .AsReadOnlyCollection(System.Array.Empty()); // Act var result = wrapped - .AsValueEnumerable() - .Count(); + .AsValueEnumerable(); // Assert _ = result.Must() - .BeEqualTo(expected); + .BeOfType>(); } - + [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -59,15 +33,27 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) .AsReadOnlyCollection(source); var expected = source .Sum(); - + // Act var result = wrapped - .AsValueEnumerable() + .AsValueEnumerable() .Sum(); - + // Assert _ = result.Must() .BeEqualTo(expected); + } + } + + public class ValueEnumerableTests1 + : ValueEnumerableTestsBase< + ReadOnlyCollectionExtensions.ValueEnumerable, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, ValueEnumerator, int>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, ValueEnumerator, int>> + { + public ValueEnumerableTests1() + : base(array => Wrap.AsReadOnlyCollection(array).AsValueEnumerable()) + { } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs similarity index 56% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.Tests.cs rename to NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs index 99625d156..2485144dd 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs @@ -2,15 +2,15 @@ using NetFabric.Assertive; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ValueEnumerable { - public partial class ValueEnumerableTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) + public void AsValueEnumerable2_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap @@ -18,7 +18,7 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) // Act var result = wrapped - .AsValueEnumerable(); + .AsValueEnumerable, int>(); // Assert _ = result.Must() @@ -30,7 +30,7 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) + public void AsValueEnumerable2_Sum_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap @@ -39,8 +39,9 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) .Sum(); // Act + // ReSharper disable once HeapView.BoxingAllocation var result = wrapped - .AsValueEnumerable() + .AsValueEnumerable, int>() .Sum(); // Assert @@ -48,4 +49,16 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(expected); } } + + public class ValueEnumerableTests2 + : ValueEnumerableTestsBase< + ValueEnumerableExtensions.ValueEnumerable, int>, + ValueEnumerableExtensions.SkipEnumerable>, Wrap.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable>, Wrap.Enumerator, int>> + { + public ValueEnumerableTests2() + // ReSharper disable once HeapView.BoxingAllocation + : base(array => Wrap.AsValueEnumerable(array).AsValueEnumerable, int>()) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs similarity index 54% rename from NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs rename to NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs index 48ef26ecb..eeb47dfde 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs @@ -2,23 +2,24 @@ using NetFabric.Assertive; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ValueReadOnlyCollection { - public partial class ValueReadOnlyCollectionTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueReadOnlyCollection1_With_ValidData_Must_Succeed(int[] source) + public void AsValueReadOnlyCollection2_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap .AsValueReadOnlyCollection(source); // Act + // ReSharper disable once HeapView.BoxingAllocation var result = wrapped - .AsValueEnumerable(); + .AsValueEnumerable, int>(); // Assert _ = result.Must() @@ -30,29 +31,7 @@ public void AsValueReadOnlyCollection1_With_ValidData_Must_Succeed(int[] source) [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueReadOnlyCollection1_Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyCollection(source); - var expected = source - .Count(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueReadOnlyCollection1_Sum_With_ValidData_Must_Succeed(int[] source) + public void AsValueReadOnlyCollection2_Sum_With_ValidData_Must_Succeed(int[] source) { // Arrange var wrapped = Wrap @@ -61,8 +40,9 @@ public void AsValueReadOnlyCollection1_Sum_With_ValidData_Must_Succeed(int[] sou .Sum(); // Act + // ReSharper disable once HeapView.BoxingAllocation var result = wrapped - .AsValueEnumerable() + .AsValueEnumerable, int>() .Sum(); // Assert @@ -70,4 +50,16 @@ public void AsValueReadOnlyCollection1_Sum_With_ValidData_Must_Succeed(int[] sou .BeEqualTo(expected); } } + + public class ValueReadOnlyCollectionTests2 + : ValueEnumerableTestsBase< + ValueReadOnlyCollectionExtensions.ValueEnumerable, int>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable>, Wrap.Enumerator, int>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable>, Wrap.Enumerator, int>> + { + public ValueReadOnlyCollectionTests2() + // ReSharper disable once HeapView.BoxingAllocation + : base(array => Wrap.AsValueReadOnlyCollection(array).AsValueEnumerable, int>()) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs index abb36fdea..1e10aeb6d 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs @@ -3,75 +3,89 @@ using System.Collections.Generic; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.Enumerable { - public partial class EnumerableTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - - // Act - var result = wrapped - .AsValueEnumerable, Wrap.Enumerator, int>( - enumerable => enumerable.GetEnumerator()); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source); - } + public partial class Tests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsEnumerable(source); + + // Act + var result = wrapped + .AsValueEnumerable, Wrap.Enumerator, int>( + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsEnumerable(source); + + // Act + var result = wrapped + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsEnumerable(source); + var expected = source + .Sum(); + + // Act + var result = wrapped + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + } - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - - // Act - var result = wrapped - .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( - enumerable => enumerable.GetEnumerator(), - enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsEnumerable(source); - var expected = source - .Sum(); - - // Act - var result = wrapped - .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( - enumerable => enumerable.GetEnumerator(), - enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } + public class ValueEnumerableTests6 + : ValueEnumerableTestsBase< + EnumerableExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, + ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>> + { + public ValueEnumerableTests6() + : base(array => Wrap + .AsEnumerable(array) + .AsValueEnumerable, Wrap.Enumerator, int>(enumerable => enumerable.GetEnumerator())) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs index a7911b8d9..81edd6d91 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs @@ -3,103 +3,93 @@ using System.Collections.Generic; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ReadOnlyCollection { - public partial class ReadOnlyCollectionTests - { - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, int>( - wrapped, - enumerable => enumerable.GetEnumerator()); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( - wrapped, - enumerable => enumerable.GetEnumerator(), - enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source); - } + public partial class Tests + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator()); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) + { + // Arrange + var wrapped = Wrap + .AsReadOnlyCollection(source); + var expected = source + .Sum(); + + // Act + var result = ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( + wrapped, + enumerable => enumerable.GetEnumerator(), + enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + + } - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = source - .Count(); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( - wrapped, - enumerable => enumerable.GetEnumerator(), - enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyCollection(source); - var expected = source - .Sum(); - - // Act - var result = ReadOnlyCollectionExtensions - .AsValueEnumerable, Wrap.Enumerator, ValueEnumerator, int>( - wrapped, - enumerable => enumerable.GetEnumerator(), - enumerable => new ValueEnumerator(((IEnumerable)enumerable).GetEnumerator())) - .Sum(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - } + public class ValueEnumerableTests6 + : ValueEnumerableTestsBase< + ReadOnlyCollectionExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>> + { + public ValueEnumerableTests6() + : base(array => ReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, int>( + Wrap.AsReadOnlyCollection(array), + enumerable => enumerable.GetEnumerator())) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs index 5c933ab0c..80a7a4e7b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs @@ -1,11 +1,10 @@ using System.Linq; using NetFabric.Assertive; -using System.Collections.Generic; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ValueEnumerable { - public partial class ValueEnumerableTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -75,4 +74,16 @@ public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(expected); } } + + public class ValueEnumerableTests6 + : ValueEnumerableTestsBase< + ValueEnumerableExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, + ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, int>> + { + public ValueEnumerableTests6() + : base(array => ValueEnumerableExtensions + .AsValueEnumerable, Wrap.Enumerator, int>(Wrap.AsValueEnumerable(array), enumerable => enumerable.GetEnumerator())) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs index fd662cde5..5f3357786 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ValueReadOnlyCollection { - public partial class ValueReadOnlyCollectionTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -51,30 +51,6 @@ public void AsValueEnumerable6_Enumerator2_With_ValidData_Must_Succeed(int[] sou .BeEqualTo(source); } - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void AsValueEnumerable6_Count_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyCollection(source); - var expected = source - .Count(); - - // Act - var result = ValueEnumerableExtensions - .AsValueEnumerable, Wrap.Enumerator, int>( - wrapped, - enumerable => enumerable.GetEnumerator()) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -99,4 +75,16 @@ public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(expected); } } + + public class ValueEnumerableTests6 + : ValueEnumerableTestsBase< + ValueReadOnlyCollectionExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>, + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>> + { + public ValueEnumerableTests6() + : base(array => ValueReadOnlyCollectionExtensions + .AsValueEnumerable, Wrap.Enumerator, int>(Wrap.AsValueReadOnlyCollection(array), enumerable => enumerable.GetEnumerator())) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs index f074dee01..ab11b0ee5 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs @@ -1,11 +1,11 @@ -using System.Linq; using NetFabric.Assertive; using System; +using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ArraySegment { - public partial class ArraySegmentTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -21,82 +21,9 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) .AsValueEnumerable(); // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source, testRefStructs: false); result.SequenceEqual(source).Must().BeTrue(); } - [Theory] - [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = source - .Skip(count0) - .Skip(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(count0) - .Skip(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = source - .Take(count0) - .Take(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Take(count0) - .Take(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = new ArraySegment(source); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Act - var result = wrapped.AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] @@ -111,7 +38,8 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int .Sum(); // Act - var result = wrapped.AsValueEnumerable() + var result = wrapped + .AsValueEnumerable() .Skip(skipCount) .Take(takeCount) .Sum(); @@ -121,4 +49,12 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int .BeEqualTo(expected); } } + + public class ArraySegmentValueEnumerableTests + : ValueEnumerableTestsBase> + { + public ArraySegmentValueEnumerableTests() + : base(array => new ArraySegment(array).AsValueEnumerable()) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs index 73cd22e55..59fb2b3cb 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Linq; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ReadOnlyList { - public class ReadOnlyListTests + public class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -27,105 +27,6 @@ public void AsValueEnumerable_With_ValidData_Must_Succeed(int[] source) .BeEnumerableOf() .BeEqualTo(wrapped); } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToArray_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .ToArray(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] - public void AsValueEnumerable_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = source - .Skip(count0) - .Skip(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(count0) - .Skip(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = source - .Take(count0) - .Take(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Take(count0) - .Take(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = Wrap - .AsReadOnlyList(source); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } [Theory] [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] @@ -153,4 +54,12 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int .BeEqualTo(expected); } } + + public class ValueEnumerableTests + : ValueEnumerableTestsBase, int>> + { + public ValueEnumerableTests() + : base(array => Wrap.AsReadOnlyList(array).AsValueEnumerable()) + {} + } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs index 839b6bc1d..df4989adc 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs @@ -1,11 +1,11 @@ -using System.Linq; using NetFabric.Assertive; using System; +using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ReadOnlyMemory { - public partial class ReadOnlyMemoryTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -21,83 +21,9 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) .AsValueEnumerable(); // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(source, testRefStructs: false); result.SequenceEqual(source).Must().BeTrue(); } - [Theory] - [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = (ReadOnlyMemory)source.AsMemory(); - var expected = source - .Skip(count0) - .Skip(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(count0) - .Skip(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = (ReadOnlyMemory)source.AsMemory(); - var expected = source - .Take(count0) - .Take(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Take(count0) - .Take(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = (ReadOnlyMemory)source.AsMemory(); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] @@ -123,4 +49,12 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int .BeEqualTo(expected); } } + + public class MemoryValueEnumerableTests + : ValueEnumerableTestsBase> + { + public MemoryValueEnumerableTests() + : base(array => ((ReadOnlyMemory)array.AsMemory()).AsValueEnumerable()) + {} + } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs index 112315775..451db31bc 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.Tests.cs @@ -3,9 +3,9 @@ using System; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ReadOnlySpan { - public partial class ReadOnlySpanTests + public partial class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -24,71 +24,6 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) result.SequenceEqual(source).Must().BeTrue(); } - [Theory] - [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = (ReadOnlySpan)source.AsSpan(); - var expected = source - .Skip(count0) - .Skip(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(count0) - .Skip(count1); - - // Assert - result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Take_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = (ReadOnlySpan)source.AsSpan(); - var expected = source - .Take(count0) - .Take(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Take(count0) - .Take(count1); - - // Assert - result.SequenceEqual(expected).Must().BeTrue(); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = (ReadOnlySpan)source.AsSpan(); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueReadOnlyList.Tests.cs index aa5fb3631..fb7aae86c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ValueReadOnlyList.Tests.cs @@ -2,9 +2,9 @@ using Xunit; using System.Linq; -namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable +namespace NetFabric.Hyperlinq.UnitTests.Conversion.AsValueEnumerable.ValueReadOnlyList { - public class ValueReadOnlyListTests + public class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -27,105 +27,6 @@ public void AsValueEnumerable_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(wrapped); } - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable_With_ToArray_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyList(source); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .ToArray(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] - public void AsValueEnumerable_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyList(source); - var expected = source - .Skip(count0) - .Skip(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(count0) - .Skip(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Take_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyList(source); - var expected = source - .Take(count0) - .Take(count1); - - // Act - var result = wrapped - .AsValueEnumerable() - .Take(count0) - .Take(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void AsValueEnumerable1_Count_With_ValidData_Must_Succeed(int[] source, int skipCount, int takeCount) - { - // Arrange - var wrapped = Wrap - .AsValueReadOnlyList(source); - var expected = source - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Act - var result = wrapped - .AsValueEnumerable() - .Skip(skipCount) - .Take(takeCount) - .Count(); - - // Assert - _ = result.Must() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs index e9d142ba7..284d53f1c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ArraySegment.Tests.cs @@ -32,7 +32,7 @@ public void Where_With_NullArray_Must_Succeed() public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Where(predicate); @@ -55,7 +55,7 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, public void Where_Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate0, Func predicate1) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Where(predicate0) @@ -80,7 +80,7 @@ public void Where_Where_With_ValidData_Must_Succeed(int[] source, int skip, int public void Where_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Where(predicate) diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs index 405191291..28b2c4d22 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs @@ -32,7 +32,7 @@ public void Where_With_NullArray_Must_Succeed() public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = Enumerable .Where(wrapped, predicate); @@ -55,7 +55,7 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, public void Where_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = Enumerable .Where(wrapped, predicate) diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs index da4512a1c..116d04843 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs @@ -33,7 +33,7 @@ public void WhereSelect_With_NullArray_Must_Succeed() public void WhereSelect_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate, Func selector) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Where(predicate) @@ -58,7 +58,7 @@ public void WhereSelect_With_ValidData_Must_Succeed(int[] source, int skip, int public void WhereSelect_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func predicate) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = Enumerable .Where(wrapped, predicate) diff --git a/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj b/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj index 3c4481d54..92306774a 100644 --- a/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj +++ b/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj @@ -16,6 +16,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -37,4 +38,8 @@ + + + + diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs index 763235721..d62a6391e 100644 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs @@ -2,9 +2,9 @@ using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip +namespace NetFabric.Hyperlinq.UnitTests.Partitioning.Skip.ValueEnumerable { - public class ValueEnumerableTests + public class Tests { [Theory] [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] @@ -27,51 +27,18 @@ public void Skip_With_ValidData_Must_Succeed(int[] source, int count) .BeEnumerableOf() .BeEqualTo(expected); } - - [Theory] - [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] - public void Skip_Skip_With_ValidData_Must_Succeed(int[] source, int count0, int count1) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - var expected = source - .Skip(count0) - .Skip( count1); - - // Act - var result = wrapped - .Skip, Wrap.Enumerator, int>(count0) - .Skip(count1); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Skip_Take_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var wrapped = Wrap - .AsValueEnumerable(source); - var expected = source - .Skip(skip) - .Take(take); - - // Act - var result = wrapped - .Skip, Wrap.Enumerator, int>(skip) - .Take(take); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } + } + + public class SkipEnumerableTests + : ValueEnumerableTestsBase< + ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, + ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, + ValueEnumerableExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>> + { + public SkipEnumerableTests() + : base(array => Wrap + .AsValueEnumerable(array) + .Skip, Wrap.Enumerator, int>(0)) + {} } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs index 4594c50e4..fdfad686c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs @@ -32,7 +32,7 @@ public void Select_With_NullArray_Must_Succeed() public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func selector) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Select(selector); @@ -55,7 +55,7 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, public void Select_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = Enumerable .Select(wrapped, item => item) diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs index c6f2db9b6..ef3153fc1 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs @@ -32,7 +32,7 @@ public void Select_With_NullArray_Must_Succeed() public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, Func selector) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Select(selector); @@ -55,7 +55,7 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, public void Select_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Select((item, _) => item) diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs index 210557769..385556359 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs @@ -4,9 +4,9 @@ using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct +namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct.ArraySegment { - public class ArraySegmentTests + public class Tests { [Fact] public void Distinct_With_NullArray_Must_Succeed() @@ -33,7 +33,7 @@ public void Distinct_With_NullArray_Must_Succeed() public void Distinct_With_ValidData_Must_Succeed(int[] source, int skip, int take) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Distinct(); @@ -49,78 +49,6 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source, int skip, int tak _ = result.SequenceEqual(expected).Must().BeTrue(); } - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = wrapped - .Distinct() - .ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Distinct() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var pool = ArrayPool.Shared; - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = wrapped - .Distinct() - .ToArray(); - - // Act - using var result = wrapped.AsValueEnumerable() - .Distinct() - .ToArray(pool); - - // Assert - _ = result - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source, int skip, int take) - { - // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); - var wrapped = new ArraySegment(source, offset, count); - var expected = wrapped - .Distinct() - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Distinct() - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] @@ -128,7 +56,7 @@ public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source, int skip, public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) { // Arrange - var (offset, count) = Utils.SkipTake(source.Length, skip, take); + var (offset, count) = Partition.SkipTake(source.Length, skip, take); var wrapped = new ArraySegment(source, offset, count); var expected = wrapped .Distinct() @@ -144,4 +72,15 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int .BeEqualTo(expected); } } + + public class ArraySegmentDistinctEnumerableTests + : ValueEnumerableTestsBase< + ArrayExtensions.ArraySegmentDistinctEnumerable, + ValueEnumerableExtensions.SkipEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int>> + { + public ArraySegmentDistinctEnumerableTests() + : base(array => new ArraySegment(array).AsValueEnumerable().Distinct()) + {} + } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs index 25a111f94..bee5e875a 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs @@ -4,9 +4,9 @@ using System.Threading.Tasks; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct +namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct.AsyncValueEnumerable { - public class AsyncValueEnumerableTests + public class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs index 9f280e6d5..4068b3c4b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs @@ -4,9 +4,9 @@ using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct +namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct.ReadOnlyMemory { - public class ReadOnlyMemoryTests + public class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -30,74 +30,6 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) _ = result.SequenceEqual(expected).Must().BeTrue(); } - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = (ReadOnlyMemory)source.AsMemory(); - var expected = - source.Distinct().ToArray(); - - // Act - var result = wrapped.AsValueEnumerable() - .Distinct() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var pool = ArrayPool.Shared; - var wrapped = (ReadOnlyMemory)source.AsMemory(); - var expected = source - .Distinct() - .ToArray(); - - // Act - using var result = wrapped.AsValueEnumerable() - .Distinct() - .ToArray(pool); - - // Assert - _ = result - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = (ReadOnlyMemory)source.AsMemory(); - var expected = source - .Distinct() - .ToList(); - - // Act - var result = wrapped.AsValueEnumerable() - .Distinct() - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -120,4 +52,14 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(expected); } } + + public class MemoryDistinctEnumerableTests + : ValueEnumerableTestsBase, + ValueEnumerableExtensions.SkipEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int>> + { + public MemoryDistinctEnumerableTests() + : base(array => ((ReadOnlyMemory)array.AsMemory()).AsValueEnumerable().Distinct()) + {} + } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs index e4c6457ad..6f30a9a08 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlySpan.Tests.cs @@ -4,9 +4,9 @@ using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct +namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct.ReadOnlySpan { - public class ReadOnlySpanTests + public class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs index 5066776eb..ffc95536b 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs @@ -3,9 +3,9 @@ using System.Linq; using Xunit; -namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct +namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct.ValueEnumerable { - public class ValueEnumerableTests + public class Tests { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -28,75 +28,6 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(expected); } - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap.AsValueEnumerable(source); - var expected = source - .Distinct() - .ToArray(); - - // Act - var result = wrapped - .Distinct, Wrap.Enumerator, int>() - .ToArray(); - - // Assert - _ = result.Must() - .BeArrayOf() - .BeEqualTo(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToArray_MemoryPool_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var pool = ArrayPool.Shared; - var wrapped = Wrap.AsValueEnumerable(source); - var expected = source - .Distinct() - .ToArray(); - - // Act - using var result = wrapped - .Distinct, Wrap.Enumerator, int>() - .ToArray(pool); - - // Assert - _ = result.Memory - .SequenceEqual(expected); - } - - [Theory] - [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] - public void Distinct_ToList_With_ValidData_Must_Succeed(int[] source) - { - // Arrange - var wrapped = Wrap.AsValueEnumerable(source); - var expected = source - .Distinct() - .ToList(); - - // Act - var result = wrapped - .Distinct, Wrap.Enumerator, int>() - .ToList(); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected); - } - [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] @@ -119,4 +50,14 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source) .BeEqualTo(expected); } } + + public class DistinctEnumerableTests + : ValueEnumerableTestsBase, Wrap.Enumerator, int>, + ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int>> + { + public DistinctEnumerableTests() + : base(array => Wrap.AsValueEnumerable(array).AsValueEnumerable().Distinct()) + {} + } } diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs new file mode 100644 index 000000000..a5b20bd54 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs @@ -0,0 +1,71 @@ +using NetFabric.Assertive; +using System.Buffers; +using System.Linq; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests.Set.Distinct.ReadOnlyList +{ + public class Tests + { + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Distinct_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyList(source); + var expected = source + .Skip(skip) + .Take(take) + .Distinct(); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(skip) + .Take(take) + .Distinct(); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int take) + { + // Arrange + var wrapped = Wrap.AsValueReadOnlyList(source); + var expected = source + .Skip(skip) + .Take(take) + .Distinct() + .Sum(); + + // Act + var result = wrapped.AsValueEnumerable() + .Skip(skip) + .Take(take) + .Distinct() + .Sum(); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } + + public class DistinctEnumerableTests + : ValueEnumerableTestsBase, int>, + ValueEnumerableExtensions.SkipEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int>, + ValueEnumerableExtensions.TakeEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int>> + { + public DistinctEnumerableTests() + : base(array => Wrap.AsValueReadOnlyList(array).AsValueEnumerable().Distinct()) + {} + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/ExpressionEx.cs b/NetFabric.Hyperlinq.UnitTests/Utils/ExpressionEx.cs new file mode 100644 index 000000000..42593fb33 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/Utils/ExpressionEx.cs @@ -0,0 +1,140 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public static partial class ExpressionEx + { + public static Expression ForEach(Expression enumerable, Expression loopContent) + { + var enumerableType = enumerable.Type; + var getEnumerator = enumerableType.GetMethod("GetEnumerator") + ?? typeof(IEnumerable<>).MakeGenericType(typeof(TSource)).GetMethod("GetEnumerator"); + var enumeratorType = getEnumerator.ReturnType; + var enumerator = Expression.Variable(enumeratorType, "enumerator"); + + return Expression.Block(new[] { enumerator }, + Expression.Assign(enumerator, Expression.Call(enumerable, getEnumerator)), + EnumerationLoop(enumerator, loopContent)); + } + + public static Expression ForEach(Expression enumerable, ParameterExpression loopVar, Expression loopContent) + { + var enumerableType = enumerable.Type; + var getEnumerator = enumerableType.GetMethod("GetEnumerator") + ?? typeof(IEnumerable<>).MakeGenericType(typeof(TSource)).GetMethod("GetEnumerator"); + var enumeratorType = getEnumerator.ReturnType; + var enumerator = Expression.Variable(enumeratorType, "enumerator"); + + return Expression.Block(new[] { enumerator }, + Expression.Assign(enumerator, Expression.Call(enumerable, getEnumerator)), + EnumerationLoop(enumerator, + Expression.Block(new[] { loopVar }, + Expression.Assign(loopVar, Expression.Property(enumerator, "Current")), + loopContent))); + } + + static Expression EnumerationLoop(ParameterExpression enumerator, Expression loopContent) + { + var loop = While( + Expression.Call(enumerator, typeof(IEnumerator).GetMethod("MoveNext")), + loopContent); + + var enumeratorType = enumerator.Type; + if (typeof(IDisposable).IsAssignableFrom(enumeratorType)) + return Using(enumerator, loop); + + if (!enumeratorType.IsValueType) + { + var disposable = Expression.Variable(typeof(IDisposable), "disposable"); + return Expression.TryFinally( + loop, + Expression.Block(new[] { disposable }, + Expression.Assign(disposable, Expression.TypeAs(enumerator, typeof(IDisposable))), + Expression.IfThen( + Expression.NotEqual(disposable, Expression.Constant(null)), + Expression.Call(disposable, typeof(IDisposable).GetMethod("Dispose"))))); + } + + return loop; + } + + public static Expression Using(ParameterExpression variable, Expression content) + { + return variable.Type switch + { + {IsValueType: true} => ValueTypeUsing(variable, content), + + _ => ReferenceTypeUsing(variable, content) + }; + + static Expression ValueTypeUsing(Expression variable, Expression content) + { +#if NETCOREAPP2_1_OR_GREATER + return variable.Type.GetCustomAttribute() switch + { + null => ValueTypeUsing(variable, content), + + _ => ByRefLikeValueTypeUsing(variable, content) + }; +#else + return ValueTypeUsing(variable, content); +#endif + + static Expression ValueTypeUsing(Expression variable, Expression content) + => typeof(IDisposable).IsAssignableFrom(variable.Type) switch + { + false => ThrowMustBeImplicitlyConvertibleToIDisposable(variable), + + _ => Expression.TryFinally( + content, + Expression.Call(Expression.Convert(variable, typeof(IDisposable)), typeof(IDisposable).GetMethod("Dispose")!)) + }; + + static Expression ByRefLikeValueTypeUsing(Expression variable, Expression content) + { + var disposeMethod = variable.Type.GetMethod("Dispose"); + return disposeMethod switch + { + null => ThrowMustBeImplicitlyConvertibleToIDisposable(variable), + + _ => Expression.TryFinally( + content, + Expression.Call(Expression.Convert(variable, typeof(IDisposable)), disposeMethod)) + }; + } + } + + static Expression ReferenceTypeUsing(Expression variable, Expression content) + => typeof(IDisposable).IsAssignableFrom(variable.Type) switch + { + false => ThrowMustBeImplicitlyConvertibleToIDisposable(variable), + + _ => Expression.TryFinally( + content, + Expression.IfThen( + Expression.NotEqual(variable, Expression.Constant(null)), + Expression.Call(Expression.Convert(variable, typeof(IDisposable)), typeof(IDisposable).GetMethod("Dispose")!))) + }; + + static T ThrowMustBeImplicitlyConvertibleToIDisposable(Expression variable) + => throw new Exception($"'{variable.Type.FullName}': type used in a using statement must be implicitly convertible to 'System.IDisposable'"); + } + + public static Expression While(Expression loopCondition, Expression loopContent) + { + var breakLabel = Expression.Label(); + return Expression.Loop( + Expression.IfThenElse( + loopCondition, + loopContent, + Expression.Break(breakLabel)), + breakLabel); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Utils/GetOperationCallExpression.cs b/NetFabric.Hyperlinq.UnitTests/Utils/GetOperationCallExpression.cs new file mode 100644 index 000000000..4276dee66 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/Utils/GetOperationCallExpression.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace NetFabric.Hyperlinq.UnitTests +{ + static class ExpressionBuilder + { + public static Expression OperationCall(string name, Expression source) + => OperationCall(name, source, out _, null, null, null); + + public static Expression OperationCall(string name, Expression source, Type[] genericTypeArguments) + => OperationCall(name, source, out _, genericTypeArguments, null, null); + + public static Expression OperationCall(string name, Expression source, out MethodInfo methodInfo) + => OperationCall(name, source, out methodInfo, null, null, null); + + public static Expression OperationCall(string name, Expression source, Type[] genericTypeArguments, out MethodInfo methodInfo) + => OperationCall(name, source, out methodInfo, genericTypeArguments, null, null); + + public static Expression OperationCall(string name, Expression source, Type[] parameterTypes, Expression[] parameterExpressions) + => OperationCall(name, source, out _, null, parameterTypes, parameterExpressions); + + public static Expression OperationCall(string name, Expression source, Type[] genericTypeArguments, Type[] parameterTypes, Expression[] parameterExpressions) + => OperationCall(name, source, out _, genericTypeArguments, parameterTypes, parameterExpressions); + + public static Expression OperationCall(string name, Expression source, Type[] parameterTypes, Expression[] parameterExpressions, out MethodInfo methodInfo) + => OperationCall(name, source, out methodInfo, null, parameterTypes, parameterExpressions); + + public static Expression OperationCall(string name, Expression source, Type[] genericTypeArguments, Type[] parameterTypes, Expression[] parameterExpressions, out MethodInfo methodInfo) + => OperationCall(name, source, out methodInfo, genericTypeArguments, parameterTypes, parameterExpressions); + + static Expression OperationCall(string name, Expression source, out MethodInfo methodInfo, Type[]? genericTypeArguments, Type[]? parameterTypes, Expression[]? parameterExpressions) + { + // check for an instance method + methodInfo = GetInstanceMethod(name, parameterTypes)!; + if (methodInfo is not null) + { + if (methodInfo.IsGenericMethod) + methodInfo = methodInfo.MakeGenericMethod(genericTypeArguments + ?? throw new ArgumentNullException(nameof(genericTypeArguments), $"{methodInfo.Name} is generic and requires type arguments!")); + + return Expression.Call(source, methodInfo, parameterExpressions); + } + + // check for an extension method + methodInfo = GetExtensionMethod(name, parameterTypes) + ?? throw new Exception($"'Operation '{ name }' not found for { typeof(TEnumerable).FullName }."); + + if (methodInfo.IsGenericMethod) + methodInfo = methodInfo.MakeGenericMethod(source.Type.GenericTypeArguments); + + IEnumerable callArguments = new[] { source }; + if (parameterExpressions is { Length: not 0 }) + callArguments = callArguments.Concat(parameterExpressions); + return Expression.Call(methodInfo, callArguments); + } + + static MethodInfo? GetInstanceMethod(string name, Type[]? parameterTypes = null) + => typeof(T).GetMethods() + .FirstOrDefault(info => + !info.IsStatic + && info.IsPublic + && info.Name == name + && info.GetCustomAttribute() is null + && info.GetParameters() + .Select(info => info.ParameterType) + .SequenceEqual(parameterTypes ?? Enumerable.Empty(), new TypeNameComparer())); + + static MethodInfo? GetExtensionMethod(string name, IReadOnlyCollection? parameterTypes = null) + { + var declaringType = typeof(T).DeclaringType!; + var parameterCount = parameterTypes?.Count + 1 ?? 1; + var genericTypeDefinition = typeof(T).GetGenericTypeDefinition(); + return declaringType.GetMethods() + .FirstOrDefault(info => + info.IsStatic + && info.IsPublic + && info.Name == name + && info.GetCustomAttribute() is not null + && info.GetParameters().Length == parameterCount + && RemoveRef(info.GetParameters()[0].ParameterType.Name) == genericTypeDefinition.Name); + } + + static string RemoveRef(string name) + => name is { Length: 0 } || name[name.Length - 1] != '&' + ? name + : name.Substring(0, name.Length - 1); + + class TypeNameComparer + : IEqualityComparer + { + public bool Equals(Type? x, Type? y) + => x?.Name == y?.Name; + + public int GetHashCode(Type obj) + => obj?.Name.GetHashCode() ?? 0; + } + + class TypeDefinitionNameComparer + : IEqualityComparer + { + public bool Equals(Type? x, Type? y) + => GetName(x) == GetName(y); + + public int GetHashCode(Type obj) + => GetName(obj)?.GetHashCode() ?? 0; + + static string? GetName(Type? type) + => type switch + { + null => null, + _ => type.IsGenericType + ? type.GetGenericTypeDefinition().Name + : type.Name + }; + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs new file mode 100644 index 000000000..063b851b5 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs @@ -0,0 +1,90 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + { + [Theory] + [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] + public void SkipSkipMustSucceed(int[] source, int count1, int count2) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Skip(count1) + .Skip(count2); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var count1Parameter = Expression.Parameter(typeof(int), "count1"); + var count2Parameter = Expression.Parameter(typeof(int), "count2"); + var expression = SkipExpression(SkipExpression(sourceParameter, count1Parameter), count2Parameter); + var func = Expression.Lambda>(expression, sourceParameter, count1Parameter, count2Parameter).Compile(); + + // Act + var result = func(wrapped, count1, count2); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + } + + [Theory] + [MemberData(nameof(TestData.Take_Take), MemberType = typeof(TestData))] + public void TakeTakeMustSucceed(int[] source, int count1, int count2) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Take(count1) + .Take(count2); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var count1Parameter = Expression.Parameter(typeof(int), "count1"); + var count2Parameter = Expression.Parameter(typeof(int), "count2"); + var expression = TakeExpression(TakeExpression(sourceParameter, count1Parameter), count2Parameter); + var func = Expression.Lambda>(expression, sourceParameter, count1Parameter, count2Parameter).Compile(); + + // Act + var result = func(wrapped, count1, count2); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + } + + + [Theory] + [MemberData(nameof(TestData.SkipTakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipTakeMultiple), MemberType = typeof(TestData))] + public void SkipTakeMustSucceed(int[] source, int count1, int count2) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Skip(count1) + .Take(count2); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var count1Parameter = Expression.Parameter(typeof(int), "count1"); + var count2Parameter = Expression.Parameter(typeof(int), "count2"); + var expression = TakeExpression(SkipExpression(sourceParameter, count1Parameter), count2Parameter); + var func = Expression.Lambda>(expression, sourceParameter, count1Parameter, count2Parameter).Compile(); + + // Act + var result = func(wrapped, count1, count2); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + } + + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs new file mode 100644 index 000000000..a93d9ccd6 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs @@ -0,0 +1,14 @@ +using System; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + : ValueEnumerableTestsBase + where TEnumerable : struct + { + protected ValueEnumerableTestsBase(Func createInstance) + : base(createInstance) + { + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs new file mode 100644 index 000000000..3b9f69e32 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs @@ -0,0 +1,34 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + { + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveCount(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Count(); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall("Count", sourceParameter); + var func = Expression.Lambda>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs new file mode 100644 index 000000000..682e65fb5 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs @@ -0,0 +1,156 @@ +using NetFabric.Assertive; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + { + // [Fact] + // public void MustHaveAsEnumerable() + // { + // // Arrange + // + // // Act + // var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + // _ = ExpressionBuilder.OperationCall("AsEnumerable", sourceParameter, out var methodInfo); + // + // // Assert + // _ = methodInfo.Must() + // .BeNotNull(); + // // .EvaluateTrue(methodInfo => typeof(IEnumerable).IsAssignableFrom(methodInfo!.ReturnType)); + // } + + [Fact] + public void MustHaveAsValueEnumerable() + { + // Arrange + + // Act + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + _ = ExpressionBuilder.OperationCall("AsValueEnumerable", sourceParameter, out var methodInfo); + + // Assert + _ = methodInfo.Must() + .BeNotNull() + .EvaluateTrue(methodInfo => methodInfo!.ReturnType.GetGenericTypeDefinition().Name == typeof(TEnumerable).Name); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveToArray(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .ToArray(); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall("ToArray", sourceParameter); + var func = Expression.Lambda>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeOfType() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveToDictionaryKeyComparer(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .ToDictionary(item => item * 3, null); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var keySelectorParameter = Expression.Parameter(typeof(Func), "keySelector"); + var comparerParameter = Expression.Parameter(typeof(IEqualityComparer), "comparer"); + var expression = ExpressionBuilder.OperationCall( + "ToDictionary", + sourceParameter, + new[] { typeof(int) }, + new[] { typeof(Func), typeof(IEqualityComparer) }, + new[] { keySelectorParameter, comparerParameter }); + var func = Expression.Lambda, IEqualityComparer?, Dictionary>>(expression, sourceParameter, keySelectorParameter, comparerParameter).Compile(); + + // Act + var result = func(wrapped, item => item * 3, null); + + // Assert + _ = result.Must() + .BeOfType>() + .BeEnumerableOf>(); + //.BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveToDictionaryKeyValueComparer(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .ToDictionary(item => item * 3, item => item * 5); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var keySelectorParameter = Expression.Parameter(typeof(Func), "keySelector"); + var valueSelectorParameter = Expression.Parameter(typeof(Func), "valueSelector"); + var comparerParameter = Expression.Parameter(typeof(IEqualityComparer), "comparer"); + var expression = ExpressionBuilder.OperationCall( + "ToDictionary", + sourceParameter, + new[] { typeof(int), typeof(int) }, + new[] { typeof(Func), typeof(Func), typeof(IEqualityComparer) }, + new[] { keySelectorParameter, valueSelectorParameter, comparerParameter }); + var func = Expression.Lambda, Func, IEqualityComparer?, Dictionary>>(expression, sourceParameter, keySelectorParameter, valueSelectorParameter, comparerParameter).Compile(); + + // Act + var result = func(wrapped, item => item * 3, item => item * 5, null); + + // Assert + _ = result.Must() + .BeOfType>() + .BeEnumerableOf>(); + //.BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveToList(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .ToList(); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall("ToList", sourceParameter); + var func = Expression.Lambda>>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeOfType>() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs new file mode 100644 index 000000000..d6cc61079 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs @@ -0,0 +1,61 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + { + [Theory] + [MemberData(nameof(TestData.ElementAt), MemberType = typeof(TestData))] + public void MustHaveElementAt(int[] source, int index) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .ElementAt(index); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var indexParameter = Expression.Parameter(typeof(int), "index"); + var expression = ExpressionBuilder.OperationCall( + "ElementAt", + sourceParameter, + new[] { typeof(int) }, + new[] { indexParameter }); + var func = Expression.Lambda>>(expression, sourceParameter, indexParameter).Compile(); + + // Act + var result = func(wrapped, index); + + // Assert + _ = result.Must() + .EvaluateTrue(option => option.IsSome && option.Value == expected); + } + + [Theory] + [MemberData(nameof(TestData.ElementAtOutOfRange), MemberType = typeof(TestData))] + public void MustHaveElementAtOutOfRange(int[] source, int index) + { + // Arrange + var wrapped = createInstance(source); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var indexParameter = Expression.Parameter(typeof(int), "index"); + var expression = ExpressionBuilder.OperationCall( + "ElementAt", + sourceParameter, + new[] { typeof(int) }, + new[] { indexParameter }); + var func = Expression.Lambda>>(expression, sourceParameter, indexParameter).Compile(); + + // Act + var result = func(wrapped, index); + + // Assert + _ = result.Must() + .EvaluateTrue(option => option.IsNone); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs new file mode 100644 index 000000000..0527c021e --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs @@ -0,0 +1,61 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + { + [Theory] + [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] + public void MustHaveSkip(int[] source, int count) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Skip(count); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var countParameter = Expression.Parameter(typeof(int), "count"); + var expression = SkipExpression(sourceParameter, countParameter); + var func = Expression.Lambda>(expression, sourceParameter, countParameter).Compile(); + + // Act + var result = func(wrapped, count); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + } + + [Theory] + [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] + public void MustHaveTake(int[] source, int count) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Take(count); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var countParameter = Expression.Parameter(typeof(int), "count"); + var expression = TakeExpression(sourceParameter, countParameter); + var func = Expression.Lambda>(expression, sourceParameter, countParameter).Compile(); + + // Act + var result = func(wrapped, count); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(expected, testRefStructs: false); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs new file mode 100644 index 000000000..24b9b3799 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs @@ -0,0 +1,42 @@ +using NetFabric.Assertive; +using System; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTestsBase + where TEnumerable : struct + where TSkipEnumerable : struct + where TTakeEnumerable : struct + { + protected readonly Func createInstance; + + protected ValueEnumerableTestsBase(Func createInstance) + => this.createInstance = createInstance; + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustBeEnumerable(int[] source) + { + // Arrange + + // Act + var result = createInstance(source); + + // Assert + _ = result.Must() + .BeEnumerableOf() + .BeEqualTo(source, testRefStructs: false); + } + + protected static Expression SkipExpression(Expression source, Expression count) + => ExpressionBuilder.OperationCall("Skip", source, new[] { typeof(int) }, new[] { count }); + + protected static Expression TakeExpression(Expression source, Expression count) + => ExpressionBuilder.OperationCall("Take", source, new[] { typeof(int) }, new[] { count }); + + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs index f6a1ef92d..c82f69c6e 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.cs @@ -33,10 +33,10 @@ IEnumerator IEnumerable.GetEnumerator() #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - IEnumerable AsEnumerable() + public IEnumerable AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs index e5a315368..6f88865fd 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.cs @@ -77,10 +77,10 @@ bool ICollection.Remove(TSource item) #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - IReadOnlyCollection AsEnumerable() + public IReadOnlyCollection AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.cs similarity index 97% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.cs rename to NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.cs index 6ac9098a4..95a858484 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.cs @@ -38,10 +38,10 @@ IEnumerator IEnumerable.GetEnumerator() #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - IEnumerable AsEnumerable() + public IEnumerable AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.cs similarity index 79% rename from NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.cs rename to NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.cs index af5cc0269..3091860f0 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'1.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.cs @@ -12,13 +12,13 @@ public static partial class ValueReadOnlyCollectionExtensions [GeneratorIgnore] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ValueEnumerable AsValueEnumerable(this IValueReadOnlyCollection source) + public static ValueEnumerable AsValueEnumerable(this IValueReadOnlyCollection source) where TEnumerator : struct, IEnumerator => new(source); [GeneratorBindings(source: "source", sourceImplements: "IValueReadOnlyCollection`2,IValueEnumerable`2", enumerableType: "IValueReadOnlyCollection")] [StructLayout(LayoutKind.Auto)] - public readonly partial struct ValueEnumerable + public readonly partial struct ValueEnumerable : IValueReadOnlyCollection , ICollection where TEnumerator : struct, IEnumerator @@ -82,68 +82,68 @@ bool ICollection.Remove(TSource item) #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - IReadOnlyCollection AsEnumerable() + public IReadOnlyCollection AsEnumerable() => source; #endregion } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this ValueEnumerable source) + public static int Count(this ValueEnumerable source) where TEnumerator : struct, IEnumerator => source.Count; [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) + public static int Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, int, int>(source); + => Sum, TEnumerator, int, int>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Sum(this ValueEnumerable source) + public static int Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, int?, int>(source); + => Sum, TEnumerator, int?, int>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) + public static long Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, long, long>(source); + => Sum, TEnumerator, long, long>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static long Sum(this ValueEnumerable source) + public static long Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, long?, long>(source); + => Sum, TEnumerator, long?, long>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) + public static float Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, float, float>(source); + => Sum, TEnumerator, float, float>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float Sum(this ValueEnumerable source) + public static float Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, float?, float>(source); + => Sum, TEnumerator, float?, float>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) + public static double Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, double, double>(source); + => Sum, TEnumerator, double, double>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double Sum(this ValueEnumerable source) + public static double Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, double?, double>(source); + => Sum, TEnumerator, double?, double>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) + public static decimal Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, decimal, decimal>(source); + => Sum, TEnumerator, decimal, decimal>(source); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static decimal Sum(this ValueEnumerable source) + public static decimal Sum(this ValueEnumerable source) where TEnumerator : struct, IEnumerator - => Sum, TEnumerator, decimal?, decimal>(source); + => Sum, TEnumerator, decimal?, decimal>(source); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs index e1a65477d..6d0e27e72 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.cs @@ -71,10 +71,10 @@ IEnumerator IEnumerable.GetEnumerator() #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - TEnumerable AsEnumerable() + public TEnumerable AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs index fdb935fd6..fe98bd8f5 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.cs @@ -117,10 +117,10 @@ bool ICollection.Remove(TSource item) #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - TEnumerable AsEnumerable() + public TEnumerable AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.cs index 11501b987..599754b5a 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.cs @@ -74,10 +74,10 @@ IEnumerator IEnumerable.GetEnumerator() #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - TEnumerable AsEnumerable() + public TEnumerable AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.cs index d61b4fee3..48993beee 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.cs @@ -117,10 +117,10 @@ bool ICollection.Remove(TSource item) #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - TEnumerable AsEnumerable() + public TEnumerable AsEnumerable() => source; #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs index 9447f0251..f0702dda0 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.cs @@ -227,13 +227,13 @@ public ArraySegmentWhereAtEnumerable WhereAt(TP [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentValueEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(source.Count, count); + var (skipCount, takeCount) = Partition.Skip(source.Count, count); return new ArraySegmentValueEnumerable(new ArraySegment(source.Array!, source.Offset + skipCount, takeCount)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegmentValueEnumerable Take(int count) - => new(new ArraySegment(source.Array!, source.Offset, Utils.Take(source.Count, count))); + => new(new ArraySegment(source.Array!, source.Offset, Partition.Take(source.Count, count))); #endregion diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs index 448817a06..78f2c8361 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.cs @@ -175,22 +175,25 @@ public readonly void Dispose() { } #region Conversion - ValueEnumerable AsValueEnumerable() + public ValueEnumerable AsValueEnumerable() => this; - ValueEnumerable AsEnumerable() + public ValueEnumerable AsEnumerable() => this; #endregion #region Partitioning [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueReadOnlyListExtensions.SkipTakeEnumerable, TSource> Skip(int count) - => ValueReadOnlyListExtensions.Skip, TSource>(this, count); - + public ValueEnumerable Skip(int count) + { + var (skipCount, takeCount) = Partition.Skip(Count, count); + return new ValueEnumerable(source, offset + skipCount, takeCount); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ValueReadOnlyListExtensions.SkipTakeEnumerable, TSource> Take(int count) - => ValueReadOnlyListExtensions.Take, TSource>(this, count); + public ValueEnumerable Take(int count) + => new(source, offset, Partition.Take(Count, count)); #endregion } @@ -250,4 +253,4 @@ public static decimal Sum(this ValueEnumerable source) where TList : IReadOnlyList => source.Sum, ValueEnumerable.DisposableEnumerator, decimal?, decimal>(); } -} \ No newline at end of file +} diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs index b486fffd3..377e42c14 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs @@ -180,13 +180,13 @@ public MemoryWhereAtEnumerable WhereAt(TPredica [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryValueEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(source.Length, count); + var (skipCount, takeCount) = Partition.Skip(source.Length, count); return new MemoryValueEnumerable(source.Slice(skipCount, takeCount)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public MemoryValueEnumerable Take(int count) - => new(source.Slice(0, Utils.Take(source.Length, count))); + => new(source.Slice(0, Partition.Take(source.Length, count))); #endregion @@ -261,7 +261,7 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this MemoryValueEnumerable source) + public static int Count(this MemoryValueEnumerable source) => source.Count; [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs index 7b33b3122..575fe47f4 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs @@ -87,13 +87,13 @@ public SpanWhereAtEnumerable WhereAt(TPredicate [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanValueEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(source.Length, count); + var (skipCount, takeCount) = Partition.Skip(source.Length, count); return new SpanValueEnumerable(source.Slice(skipCount, takeCount)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanValueEnumerable Take(int count) - => new(source.Slice(0, Utils.Take(source.Length, count))); + => new(source.Slice(0, Partition.Take(source.Length, count))); #endregion @@ -168,7 +168,7 @@ public bool SequenceEqual(IEnumerable other, IEqualityComparer } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int Count(this SpanValueEnumerable source) + public static int Count(this SpanValueEnumerable source) => source.Count; [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs index 90f843bc8..05f38fcf2 100644 --- a/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq/Conversion/ToList/ToList.ValueReadOnlyCollection.cs @@ -14,13 +14,11 @@ public static List ToList(this TEnum => source switch { { Count: 0 } => new List(), - _ => source switch - { - // ReSharper disable once HeapView.PossibleBoxingAllocation - ICollection collection => new List(collection), - _ => ToArray(source).AsList(), - } + // ReSharper disable once HeapView.PossibleBoxingAllocation + ICollection collection => new List(collection), + + _ => ToArray(source).AsList(), }; [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs b/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs index 9aedd0d55..cf34ac56e 100644 --- a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs +++ b/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Range.cs @@ -133,13 +133,13 @@ public ValueTask AnyAsync(CancellationToken cancellationToken = default) [MethodImpl(MethodImplOptions.AggressiveInlining)] public RangeEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(this.count, count); + var (skipCount, takeCount) = Partition.Skip(this.count, count); return Range(start + skipCount, takeCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RangeEnumerable Take(int count) - => Range(start, Utils.Take(this.count, count)); + => Range(start, Partition.Take(this.count, count)); #pragma warning disable IDE0060 // Remove unused parameter public ValueTask ContainsAsync(int value, CancellationToken cancellationToken) diff --git a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs b/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs index 9fac293e5..bc749bdcb 100644 --- a/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs +++ b/NetFabric.Hyperlinq/Generation/AsyncValueEnumerable/Repeat.cs @@ -130,13 +130,13 @@ public readonly void Dispose() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RepeatEnumerable Skip(int count) { - var (_, takeCount) = Utils.Skip(this.count, count); + var (_, takeCount) = Partition.Skip(this.count, count); return Repeat(value, takeCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RepeatEnumerable Take(int count) - => Repeat(value, Utils.Take(this.count, count)); + => Repeat(value, Partition.Take(this.count, count)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ValueTask AllAsync(Func predicate) diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs b/NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs index b89e34708..dd33df6fc 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs +++ b/NetFabric.Hyperlinq/Generation/ValueEnumerable/Range.cs @@ -151,13 +151,13 @@ public readonly void Dispose() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RangeEnumerable Skip(int count) { - var (skipCount, takeCount) = Utils.Skip(Count, count); + var (skipCount, takeCount) = Partition.Skip(Count, count); return Range(start + skipCount, takeCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RangeEnumerable Take(int count) - => Range(start, Utils.Take(Count, count)); + => Range(start, Partition.Take(Count, count)); #endregion #region Aggregation diff --git a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs b/NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs index 90af0e24f..62b9ac7ea 100644 --- a/NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs +++ b/NetFabric.Hyperlinq/Generation/ValueEnumerable/Repeat.cs @@ -138,13 +138,13 @@ public readonly void Dispose() { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RepeatEnumerable Skip(int count) { - var (_, takeCount) = Utils.Skip(this.count, count); + var (_, takeCount) = Partition.Skip(this.count, count); return Repeat(value, takeCount); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RepeatEnumerable Take(int count) - => Repeat(value, Utils.Take(this.count, count)); + => Repeat(value, Partition.Take(this.count, count)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool All(Func predicate) diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs index 2fd69b45b..56e8bd927 100644 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.AsyncValueEnumerable.cs @@ -168,6 +168,10 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipEnumerable Skip(int count) => source.Skip(this.count + count); @@ -176,5 +180,65 @@ public SkipEnumerable Skip(int count) public SkipTakeEnumerable Take(int count) => source.SkipTake(this.count, count); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipEnumerable.Enumerator, decimal?, decimal>(); } } diff --git a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs index 6c933d9aa..0015cf9e6 100644 --- a/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Partitioning/Skip/Skip.ValueEnumerable.cs @@ -85,6 +85,10 @@ public void Dispose() => enumerator.Dispose(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipEnumerable Skip(int count) => source.Skip(this.count + count); @@ -93,5 +97,65 @@ public SkipEnumerable Skip(int count) public SkipTakeEnumerable Take(int count) => source.SkipTake(this.count, count); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SkipEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipEnumerable.Enumerator, decimal?, decimal>(); } } diff --git a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs index e92456e42..ed5b007f0 100644 --- a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.AsyncValueEnumerable.cs @@ -39,6 +39,7 @@ internal SkipTakeEnumerable(in TEnumerable source, int skipCount, int takeCount) public readonly Enumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => new(in this, cancellationToken); readonly IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this, cancellationToken); [StructLayout(LayoutKind.Auto)] @@ -216,9 +217,77 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable AsValueEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + => source.SkipTake(skipCount + Math.Max(0, count), takeCount); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(skipCount, Math.Min(takeCount, count)); + => source.SkipTake(skipCount, Partition.Take(takeCount, count)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this SkipTakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, SkipTakeEnumerable.Enumerator, decimal?, decimal>(); } } diff --git a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs b/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs index 251b0cacd..385f42a05 100644 --- a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueEnumerable.cs @@ -100,9 +100,77 @@ public void Dispose() => enumerator.Dispose(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable AsValueEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + => source.SkipTake(skipCount + Math.Max(0, count), takeCount); + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(skipCount, Math.Min(takeCount, count)); + => source.SkipTake(skipCount, Partition.Take(takeCount, count)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, SkipTakeEnumerable.Enumerator, decimal?, decimal>(); } } diff --git a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs b/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs index 9fdeaec90..bc0cc73c8 100644 --- a/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs +++ b/NetFabric.Hyperlinq/Partitioning/SkipTake/SkipTake.ValueReadOnlyCollection.cs @@ -29,7 +29,7 @@ public readonly partial struct SkipTakeEnumerable new(in this); readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); readonly IEnumerator IEnumerable.GetEnumerator() + // ReSharper disable once HeapView.BoxingAllocation => new Enumerator(in this); bool ICollection.IsReadOnly @@ -79,6 +81,7 @@ public void CopyTo(TSource[] array, int arrayIndex) if (Count is 0) return; + // ReSharper disable once HeapView.PossibleBoxingAllocation if (skipCount is 0 && Count == source.Count && source is ICollection collection) collection.CopyTo(array, arrayIndex); else @@ -237,9 +240,20 @@ static bool ComparerContains(TEnumerable source, TSource value, IEqualityCompare } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable AsValueEnumerable() + => this; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public SkipTakeEnumerable Skip(int count) + { + var (skipCount, takeCount) = Partition.Skip(Count, count); + return source.SkipTake(this.skipCount + skipCount, takeCount); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] public SkipTakeEnumerable Take(int count) - => source.SkipTake(skipCount, Math.Min(Count, count)); + => source.SkipTake(skipCount, Partition.Take(Count, count)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -247,5 +261,65 @@ public static int Count(this in SkipTakeEnume where TEnumerable : IValueReadOnlyCollection where TEnumerator : struct, IEnumerator => source.Count; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, int, int>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, int?, int>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, long, long>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, long?, long>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, float, float>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, float?, float>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, double, double>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, double?, double>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, decimal, decimal>(source); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this SkipTakeEnumerable source) + where TEnumerable : IValueReadOnlyCollection + where TEnumerator : struct, IEnumerator + => Sum, SkipTakeEnumerable.Enumerator, decimal?, decimal>(source); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs index 7ef457d0c..3135225d2 100644 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Partitioning/Take/Take.AsyncValueEnumerable.cs @@ -171,9 +171,73 @@ void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine) { } } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TakeEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TakeEnumerable Take(int count) => source.Take(Math.Min(this.count, count)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ValueTask SumAsync(this TakeEnumerable source) + where TEnumerable : IAsyncValueEnumerable + where TEnumerator : struct, IAsyncEnumerator + => source.SumAsync, TakeEnumerable.Enumerator, decimal?, decimal>(); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs b/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs index 4be64afde..5169350d7 100644 --- a/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Partitioning/Take/Take.ValueEnumerable.cs @@ -89,9 +89,73 @@ public void Dispose() => enumerator.Dispose(); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TakeEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public TakeEnumerable Take(int count) => source.Take(Math.Min(this.count, count)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, int, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, int?, int>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, long, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static long Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, long?, long>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, float, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, float?, float>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, double, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, double?, double>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, decimal, decimal>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static decimal Sum(this TakeEnumerable source) + where TEnumerable : IValueEnumerable + where TEnumerator : struct, IEnumerator + => source.Sum, TakeEnumerable.Enumerator, decimal?, decimal>(); } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs index c8482fc4e..ed9ee54ab 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ReadOnlySpan.cs @@ -77,7 +77,7 @@ static bool ContainsAt(this ReadOnlySpan s return source switch { { Length: 0 } => false, - _ => Utils.IsValueType() + _ => Utils.UseDefault(comparer) ? ValueContains(source, value, selector) : ReferenceContains(source, value, comparer, selector), }; diff --git a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs b/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs index d50c3fdfa..575dc4264 100644 --- a/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Quantifier/Contains/Contains.ValueEnumerable.cs @@ -83,7 +83,7 @@ internal static bool ContainsAt where TSelector : struct, IFunction { - return Utils.IsValueType() + return Utils.UseDefault(comparer) ? ValueContains(source, value, selector) : ReferenceContains(source, value, comparer, selector); diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs index b6fb0e3e6..cdd50e102 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs +++ b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ArraySegment.cs @@ -89,6 +89,10 @@ readonly Set GetSet() return set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly ArraySegmentDistinctEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly int Count() => source switch diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs index ead4fb045..f75317a9b 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Set/Distinct/Distinct.AsyncValueEnumerable.cs @@ -187,6 +187,10 @@ readonly async ValueTask> FillSetAsync(CancellationToken cancellati return set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly DistinctEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly async ValueTask CountAsync(CancellationToken cancellationToken = default) => (await FillSetAsync(cancellationToken).ConfigureAwait(false)).Count; diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs index 63810e374..bc605c9f9 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlyMemory.cs @@ -92,6 +92,10 @@ readonly Set GetSet() return set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly MemoryDistinctEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly int Count() => source switch diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs index 4c7c42c09..9040eaa37 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ReadOnlySpan.cs @@ -76,6 +76,10 @@ readonly Set GetSet() return set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly SpanDistinctEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly int Count() => source.Length switch diff --git a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs index 9c6a7c772..89720e4c0 100644 --- a/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs +++ b/NetFabric.Hyperlinq/Set/Distinct/Distinct.ValueEnumerable.cs @@ -99,6 +99,10 @@ readonly Set GetSet() return set; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly DistinctEnumerable AsValueEnumerable() + => this; + [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly int Count() => GetSet().Count; diff --git a/NetFabric.Hyperlinq/Utils/Utils.SkipTake.cs b/NetFabric.Hyperlinq/Utils/Partition.cs similarity index 96% rename from NetFabric.Hyperlinq/Utils/Utils.SkipTake.cs rename to NetFabric.Hyperlinq/Utils/Partition.cs index 2c438f814..f53046eda 100644 --- a/NetFabric.Hyperlinq/Utils/Utils.SkipTake.cs +++ b/NetFabric.Hyperlinq/Utils/Partition.cs @@ -3,7 +3,7 @@ namespace NetFabric.Hyperlinq { - static partial class Utils + static class Partition { [MethodImpl(MethodImplOptions.AggressiveInlining)] From 634970436ab175e98ba1e8a413365a8e9c323cca Mon Sep 17 00:00:00 2001 From: Antao Almada Date: Wed, 28 Apr 2021 23:16:04 +0100 Subject: [PATCH 2/2] NetFabric.Assertive 4.0.0-beta01 --- .../NetFabric.Hyperlinq.Benchmarks.csproj | 2 +- .../NetFabric.Hyperlinq.Immutable.csproj | 2 +- ...Hyperlinq.SourceGenerator.UnitTests.csproj | 6 +- ...NetFabric.Hyperlinq.SourceGenerator.csproj | 2 +- .../AsValueEnumerable'1.Enumerable.Tests.cs | 7 +- ...ueEnumerable'1.ReadOnlyCollection.Tests.cs | 7 +- ...ValueEnumerable'2.ValueEnumerable.Tests.cs | 7 +- ...merable'2.ValueReadOnlyCollection.Tests.cs | 7 +- .../AsValueEnumerable'6.Enumerable.Tests.cs | 7 +- ...ueEnumerable'6.ReadOnlyCollection.Tests.cs | 7 +- ...ValueEnumerable'6.ValueEnumerable.Tests.cs | 7 +- ...merable'6.ValueReadOnlyCollection.Tests.cs | 2 +- .../AsValueEnumerable.ArraySegment.Tests.cs | 7 +- .../AsValueEnumerable.ReadOnlyList.Tests.cs | 5 +- .../AsValueEnumerable.ReadOnlyMemory.Tests.cs | 7 +- .../System/Collections/Generic/List.Tests.cs | 3 +- .../Immutable/ImmutableArray.Tests.cs | 3 +- .../ToArray/ToArray.ReadOnlyList.Tests.cs | 24 +-- .../ToArray/ToArray.ValueEnumerable.Tests.cs | 24 +-- .../ToArray.ValueReadOnlyCollection.Tests.cs | 12 +- ...ToArrayAsync.AsyncValueEnumerable.Tests.cs | 24 +-- .../Where/Where.ArraySegment.Tests.cs | 9 +- .../Where/Where.ReadOnlyMemory.Tests.cs | 3 +- .../WhereAt/WhereAt.ArraySegment.Tests.cs | 6 +- .../WhereAt/WhereAt.ReadOnlyMemory.Tests.cs | 3 +- .../WhereSelect.ArraySegment.Tests.cs | 6 +- .../WhereSelect.ReadOnlyMemory.Tests.cs | 3 +- .../NetFabric.Hyperlinq.UnitTests.csproj | 7 +- .../Skip/Skip.ValueEnumerable.Tests.cs | 7 +- .../Select/Select.ArraySegment.Tests.cs | 6 +- .../Select/Select.ReadOnlyMemory.Tests.cs | 3 +- .../SelectAt/SelectAt.ArraySegment.Tests.cs | 6 +- .../SelectAt/SelectAt.ReadOnlyMemory.Tests.cs | 3 +- .../Distinct/Distinct.ArraySegment.Tests.cs | 13 +- .../Distinct.AsyncValueEnumerable.Tests.cs | 4 +- .../Distinct/Distinct.ReadOnlyMemory.Tests.cs | 10 +- .../Distinct.ValueEnumerable.Tests.cs | 7 +- .../Distinct.ValueReadOnlyList.Tests.cs | 7 +- ...eEnumerableTestsBase'4.cs => TestsBase.cs} | 10 +- ...cs => ValueEnumerableTests.Aggregation.cs} | 8 +- ....cs => ValueEnumerableTests.Conversion.cs} | 7 +- .../ValueEnumerableTests.Element.cs | 162 ++++++++++++++++++ .../ValueEnumerableTests.Filtering.cs | 76 ++++++++ ...s => ValueEnumerableTests.Partitioning.cs} | 73 +++++++- .../ValueEnumerableTests.cs | 43 +++++ .../ValueEnumerableTestsBase'1.cs | 14 -- .../ValueEnumerableTestsBase'4.Element.cs | 61 ------- ...ValueEnumerableTestsBase'4.Partitioning.cs | 61 ------- .../AsValueEnumerable.ReadOnlyMemory.cs | 39 ++--- .../AsValueEnumerable.ReadOnlySpan.cs | 8 +- .../Where/Where/Where.ReadOnlyMemory.cs | 22 --- .../NetFabric.Hyperlinq.csproj | 2 +- 52 files changed, 531 insertions(+), 330 deletions(-) rename NetFabric.Hyperlinq.UnitTests/{ValueEnumerableTestsBase'4.cs => TestsBase.cs} (79%) rename NetFabric.Hyperlinq.UnitTests/{ValueEnumerableTestsBase'4.Aggregation.cs => ValueEnumerableTests.Aggregation.cs} (82%) rename NetFabric.Hyperlinq.UnitTests/{ValueEnumerableTestsBase'4.Conversion.cs => ValueEnumerableTests.Conversion.cs} (97%) create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Element.cs create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Filtering.cs rename NetFabric.Hyperlinq.UnitTests/{ValueEnumerableTestsBase'1.Partitioning.cs => ValueEnumerableTests.Partitioning.cs} (57%) create mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.cs delete mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs delete mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs delete mode 100644 NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs diff --git a/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj b/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj index cee2d5647..2ee9c9e07 100644 --- a/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj +++ b/NetFabric.Hyperlinq.Benchmarks/NetFabric.Hyperlinq.Benchmarks.csproj @@ -18,7 +18,7 @@ - + diff --git a/NetFabric.Hyperlinq.Immutable/NetFabric.Hyperlinq.Immutable.csproj b/NetFabric.Hyperlinq.Immutable/NetFabric.Hyperlinq.Immutable.csproj index 6900f3537..82d7e43d4 100644 --- a/NetFabric.Hyperlinq.Immutable/NetFabric.Hyperlinq.Immutable.csproj +++ b/NetFabric.Hyperlinq.Immutable/NetFabric.Hyperlinq.Immutable.csproj @@ -36,7 +36,7 @@ all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers diff --git a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj index f4c4fe6cb..ff8dc1505 100644 --- a/NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj +++ b/NetFabric.Hyperlinq.SourceGenerator.UnitTests/NetFabric.Hyperlinq.SourceGenerator.UnitTests.csproj @@ -7,9 +7,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj b/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj index 991562703..e6b2bb746 100644 --- a/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj +++ b/NetFabric.Hyperlinq.SourceGenerator/NetFabric.Hyperlinq.SourceGenerator.csproj @@ -10,7 +10,7 @@ - + all diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs index 4fe6a804f..9e33dc61e 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.Enumerable.Tests.cs @@ -47,10 +47,13 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests1 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< EnumerableExtensions.ValueEnumerable, ValueEnumerableExtensions.SkipEnumerable, ValueEnumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, ValueEnumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, ValueEnumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, ValueEnumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, ValueEnumerator, int, FunctionWrapper> + > { public ValueEnumerableTests1() : base(array => Wrap.AsEnumerable(array).AsValueEnumerable()) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs index f6f98f9ac..90ea691c5 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'1.ReadOnlyCollection.Tests.cs @@ -46,10 +46,13 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests1 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ReadOnlyCollectionExtensions.ValueEnumerable, ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, ValueEnumerator, int>, - ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, ValueEnumerator, int>> + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, ValueEnumerator, int>, + ValueReadOnlyCollectionExtensions.WhereEnumerable, ValueEnumerator, int, FunctionWrapper>, + ValueReadOnlyCollectionExtensions.WhereAtEnumerable, ValueEnumerator, int, FunctionWrapper> + > { public ValueEnumerableTests1() : base(array => Wrap.AsReadOnlyCollection(array).AsValueEnumerable()) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs index 2485144dd..cc0b69b8f 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueEnumerable.Tests.cs @@ -51,10 +51,13 @@ public void AsValueEnumerable2_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests2 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ValueEnumerableExtensions.ValueEnumerable, int>, ValueEnumerableExtensions.SkipEnumerable>, Wrap.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable>, Wrap.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable>, Wrap.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable>, Wrap.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable>, Wrap.Enumerator, int, FunctionWrapper> + > { public ValueEnumerableTests2() // ReSharper disable once HeapView.BoxingAllocation diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs index eeb47dfde..af96692ab 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'2.ValueReadOnlyCollection.Tests.cs @@ -52,10 +52,13 @@ public void AsValueReadOnlyCollection2_Sum_With_ValidData_Must_Succeed(int[] sou } public class ValueReadOnlyCollectionTests2 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ValueReadOnlyCollectionExtensions.ValueEnumerable, int>, ValueReadOnlyCollectionExtensions.SkipTakeEnumerable>, Wrap.Enumerator, int>, - ValueReadOnlyCollectionExtensions.SkipTakeEnumerable>, Wrap.Enumerator, int>> + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable>, Wrap.Enumerator, int>, + ValueReadOnlyCollectionExtensions.WhereEnumerable>, Wrap.Enumerator, int, FunctionWrapper>, + ValueReadOnlyCollectionExtensions.WhereAtEnumerable>, Wrap.Enumerator, int, FunctionWrapper> + > { public ValueReadOnlyCollectionTests2() // ReSharper disable once HeapView.BoxingAllocation diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs index 1e10aeb6d..0ffe26e93 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.Enumerable.Tests.cs @@ -77,10 +77,13 @@ public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests6 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< EnumerableExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int, FunctionWrapper> + > { public ValueEnumerableTests6() : base(array => Wrap diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs index 81edd6d91..39a781d75 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ReadOnlyCollection.Tests.cs @@ -80,10 +80,13 @@ public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests6 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ReadOnlyCollectionExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>, - ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>> + ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int>, + ValueReadOnlyCollectionExtensions.WhereEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int, FunctionWrapper>, + ValueReadOnlyCollectionExtensions.WhereAtEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, Wrap.Enumerator, int, FunctionWrapper> + > { public ValueEnumerableTests6() : base(array => ReadOnlyCollectionExtensions diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs index 80a7a4e7b..54f77eb42 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueEnumerable.Tests.cs @@ -76,10 +76,13 @@ public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests6 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ValueEnumerableExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, Wrap.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, Wrap.Enumerator, int, FunctionWrapper> + > { public ValueEnumerableTests6() : base(array => ValueEnumerableExtensions diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs index 5f3357786..df1dd95bd 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable'6.ValueReadOnlyCollection.Tests.cs @@ -77,7 +77,7 @@ public void AsValueEnumerable6_Sum_With_ValidData_Must_Succeed(int[] source) } public class ValueEnumerableTests6 - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ValueReadOnlyCollectionExtensions.ValueEnumerable, Wrap.Enumerator, Wrap.Enumerator, int, FunctionWrapper, Wrap.Enumerator>, FunctionWrapper, Wrap.Enumerator>>, ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>, ValueReadOnlyCollectionExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>> diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs index ab11b0ee5..08505d4ce 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ArraySegment.Tests.cs @@ -21,7 +21,7 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) .AsValueEnumerable(); // Assert - result.SequenceEqual(source).Must().BeTrue(); + result.Must().BeEnumerableOf().BeEqualTo(source); } [Theory] @@ -51,7 +51,10 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int } public class ArraySegmentValueEnumerableTests - : ValueEnumerableTestsBase> + : ValueEnumerableTests< + ArrayExtensions.ArraySegmentValueEnumerable, + ValueEnumerableExtensions.WhereEnumerable, ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, ArrayExtensions.ArraySegmentValueEnumerable.DisposableEnumerator, int, FunctionWrapper>> { public ArraySegmentValueEnumerableTests() : base(array => new ArraySegment(array).AsValueEnumerable()) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs index 59fb2b3cb..dc0251a19 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyList.Tests.cs @@ -56,7 +56,10 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int } public class ValueEnumerableTests - : ValueEnumerableTestsBase, int>> + : ValueEnumerableTests< + ReadOnlyListExtensions.ValueEnumerable, int>, + ValueEnumerableExtensions.WhereEnumerable, int>, ReadOnlyListExtensions.ValueEnumerable, int>.DisposableEnumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, int>, ReadOnlyListExtensions.ValueEnumerable, int>.DisposableEnumerator, int, FunctionWrapper>> { public ValueEnumerableTests() : base(array => Wrap.AsReadOnlyList(array).AsValueEnumerable()) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs index df4989adc..7df8ee499 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.Tests.cs @@ -21,7 +21,7 @@ public void AsValueEnumerable1_With_ValidData_Must_Succeed(int[] source) .AsValueEnumerable(); // Assert - result.SequenceEqual(source).Must().BeTrue(); + result.Must().BeEnumerableOf().BeEqualTo(source); } [Theory] @@ -51,7 +51,10 @@ public void AsValueEnumerable1_Sum_With_ValidData_Must_Succeed(int[] source, int } public class MemoryValueEnumerableTests - : ValueEnumerableTestsBase> + : ValueEnumerableTests< + ArrayExtensions.MemoryValueEnumerable, + ValueEnumerableExtensions.WhereEnumerable, ArrayExtensions.MemoryValueEnumerable.DisposableEnumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, ArrayExtensions.MemoryValueEnumerable.DisposableEnumerator, int, FunctionWrapper>> { public MemoryValueEnumerableTests() : base(array => ((ReadOnlyMemory)array.AsMemory()).AsValueEnumerable()) diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs index 09510ab21..259c5b20e 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Generic/List.Tests.cs @@ -24,8 +24,7 @@ public void AsValueEnumerable_With_List_Must_ReturnWrapper(int[] source) _ = result.Must() .BeOfType>() .BeEnumerableOf() - .BeEqualTo(wrapped, testRefStructs: false); - _ = result.SequenceEqual(wrapped).Must().BeTrue(); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs index d21e7e9a2..be03a90e0 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/AsValueEnumerable/Bindings/System/Collections/Immutable/ImmutableArray.Tests.cs @@ -23,8 +23,7 @@ public void AsValueEnumerable_With_ImmutableArray_Must_ReturnWrapper(int[] sourc _ = result.Must() .BeOfType>() .BeEnumerableOf() - .BeEqualTo(wrapped, testRefStructs: false); - result.SequenceEqual(wrapped).Must().BeTrue(); + .BeEqualTo(wrapped); } } } diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs index d0c43ab4c..1add1e5a7 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ReadOnlyList.Tests.cs @@ -57,8 +57,8 @@ public void ToArray_MemoryPool_Must_Succeed(int[] source, int skip, int take) .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -116,8 +116,8 @@ public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, int skip, in .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -175,8 +175,8 @@ public void ToArray_PredicateAt_MemoryPool_Must_Succeed(int[] source, int skip, .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -233,8 +233,8 @@ public void ToArray_Selector_MemoryPool_Must_Succeed(int[] source, int skip, int .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -291,8 +291,8 @@ public void ToArray_SelectorAt_MemoryPool_Must_Succeed(int[] source, int skip, i .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -353,8 +353,8 @@ public void ToArray_Predicate_Selector_MemoryPool_Must_Succeed(int[] source, int .ToArray(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } } } \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs index ccb6f82cb..955947b5e 100644 --- a/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Conversion/ToArray/ToArray.ValueEnumerable.Tests.cs @@ -70,8 +70,8 @@ public void ToArray_MemoryPool_Must_Succeed(int[] source) .ToArray, Wrap.Enumerator, int>(pool); // Assert - _ = result.Memory - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } ////////////////////////////////////////////////////////////////////////////////////////////////// @@ -120,8 +120,8 @@ public void ToArray_Predicate_MemoryPool_Must_Succeed(int[] source, Func() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -44,8 +43,7 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = Enumerable.SequenceEqual(result, expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -69,8 +67,7 @@ public void Where_Where_With_ValidData_Must_Succeed(int[] source, int skip, int // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs index 8ac2bf608..444e66a0e 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/Where/Where.ReadOnlyMemory.Tests.cs @@ -25,8 +25,7 @@ public void Where_With_ValidData_Must_Succeed(int[] source, Func pred // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs index 28b2c4d22..7cb2336c6 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ArraySegment.Tests.cs @@ -21,8 +21,7 @@ public void Where_With_NullArray_Must_Succeed() // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -44,8 +43,7 @@ public void Where_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs index 1c4ccbb49..18a7b66e3 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereAt/WhereAt.ReadOnlyMemory.Tests.cs @@ -25,8 +25,7 @@ public void Where_With_ValidData_Must_Succeed(int[] source, Func // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs index 116d04843..7c7621a72 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ArraySegment.Tests.cs @@ -22,8 +22,7 @@ public void WhereSelect_With_NullArray_Must_Succeed() // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -47,8 +46,7 @@ public void WhereSelect_With_ValidData_Must_Succeed(int[] source, int skip, int // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = Enumerable.SequenceEqual(result, expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs index 52e2035c5..c911cf4e4 100644 --- a/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Filtering/WhereSelect/WhereSelect.ReadOnlyMemory.Tests.cs @@ -27,8 +27,7 @@ public void WhereSelect_With_ValidData_Must_Succeed(int[] source, Func() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj b/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj index 92306774a..e8ae7c2f5 100644 --- a/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj +++ b/NetFabric.Hyperlinq.UnitTests/NetFabric.Hyperlinq.UnitTests.csproj @@ -10,13 +10,12 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs index d62a6391e..d5269f6c5 100644 --- a/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Partitioning/Skip/Skip.ValueEnumerable.Tests.cs @@ -30,10 +30,13 @@ public void Skip_With_ValidData_Must_Succeed(int[] source, int count) } public class SkipEnumerableTests - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, - ValueEnumerableExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>> + ValueEnumerableExtensions.SkipTakeEnumerable, Wrap.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>.Enumerator, int, FunctionWrapper> + > { public SkipEnumerableTests() : base(array => Wrap diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs index fdfad686c..09998cd13 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ArraySegment.Tests.cs @@ -21,8 +21,7 @@ public void Select_With_NullArray_Must_Succeed() // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -44,8 +43,7 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs index 7d68c66ec..76e1e707c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Projection/Select/Select.ReadOnlyMemory.Tests.cs @@ -25,8 +25,7 @@ public void Select_With_ValidData_Must_Succeed(int[] source, Func s // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected, testRefReturns: false); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs index ef3153fc1..f40b57d1c 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ArraySegment.Tests.cs @@ -21,8 +21,7 @@ public void Select_With_NullArray_Must_Succeed() // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -44,8 +43,7 @@ public void Select_With_ValidData_Must_Succeed(int[] source, int skip, int take, // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs index 3150a7fb9..3abc58670 100644 --- a/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Projection/SelectAt/SelectAt.ReadOnlyMemory.Tests.cs @@ -25,8 +25,7 @@ public void Select_With_ValidData_Must_Succeed(int[] source, Func() - .BeEqualTo(expected, testRefStructs: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs index 385556359..a3a8d4eba 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ArraySegment.Tests.cs @@ -22,8 +22,7 @@ public void Distinct_With_NullArray_Must_Succeed() // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -45,8 +44,7 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source, int skip, int tak // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -74,10 +72,13 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int } public class ArraySegmentDistinctEnumerableTests - : ValueEnumerableTestsBase< + : ValueEnumerableTests< ArrayExtensions.ArraySegmentDistinctEnumerable, ValueEnumerableExtensions.SkipEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, ArrayExtensions.ArraySegmentDistinctEnumerable.Enumerator, int, FunctionWrapper> + > { public ArraySegmentDistinctEnumerableTests() : base(array => new ArraySegment(array).AsValueEnumerable().Distinct()) diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs index bee5e875a..5f1ef2531 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.AsyncValueEnumerable.Tests.cs @@ -73,8 +73,8 @@ public async ValueTask Distinct_ToArrayAsync_MemoryPool_With_ValidData_Must_Succ .ConfigureAwait(false); // Assert - _ = result - .SequenceEqual(expected); + _ = result.Memory.Must() + .BeEqualTo(expected); } [Theory] diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs index 4068b3c4b..1d4229d32 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ReadOnlyMemory.Tests.cs @@ -26,8 +26,7 @@ public void Distinct_With_ValidData_Must_Succeed(int[] source) // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false, testRefReturns: false); - _ = result.SequenceEqual(expected).Must().BeTrue(); + .BeEqualTo(expected); } [Theory] @@ -54,9 +53,12 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source) } public class MemoryDistinctEnumerableTests - : ValueEnumerableTestsBase, + : ValueEnumerableTests, ValueEnumerableExtensions.SkipEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, ArrayExtensions.MemoryDistinctEnumerable.Enumerator, int, FunctionWrapper> + > { public MemoryDistinctEnumerableTests() : base(array => ((ReadOnlyMemory)array.AsMemory()).AsValueEnumerable().Distinct()) diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs index ffc95536b..fb5fd7a41 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueEnumerable.Tests.cs @@ -52,9 +52,12 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source) } public class DistinctEnumerableTests - : ValueEnumerableTestsBase, Wrap.Enumerator, int>, + : ValueEnumerableTests, Wrap.Enumerator, int>, ValueEnumerableExtensions.SkipEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, Wrap.Enumerator, int>, ValueEnumerableExtensions.DistinctEnumerable, Wrap.Enumerator, int>.Enumerator, int, FunctionWrapper> + > { public DistinctEnumerableTests() : base(array => Wrap.AsValueEnumerable(array).AsValueEnumerable().Distinct()) diff --git a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs index a5b20bd54..ac3d07931 100644 --- a/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs +++ b/NetFabric.Hyperlinq.UnitTests/Set/Distinct/Distinct.ValueReadOnlyList.Tests.cs @@ -60,9 +60,12 @@ public void Distinct_Sum_With_ValidData_Must_Succeed(int[] source, int skip, int } public class DistinctEnumerableTests - : ValueEnumerableTestsBase, int>, + : ValueEnumerableTests, int>, ValueEnumerableExtensions.SkipEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int>, - ValueEnumerableExtensions.TakeEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int>> + ValueEnumerableExtensions.TakeEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int>, + ValueEnumerableExtensions.WhereEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int, FunctionWrapper>, + ValueEnumerableExtensions.WhereAtEnumerable, int>, ValueReadOnlyListExtensions.DistinctEnumerable, int>.Enumerator, int, FunctionWrapper> + > { public DistinctEnumerableTests() : base(array => Wrap.AsValueReadOnlyList(array).AsValueEnumerable().Distinct()) diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs b/NetFabric.Hyperlinq.UnitTests/TestsBase.cs similarity index 79% rename from NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs rename to NetFabric.Hyperlinq.UnitTests/TestsBase.cs index 24b9b3799..466a6622d 100644 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.cs +++ b/NetFabric.Hyperlinq.UnitTests/TestsBase.cs @@ -5,14 +5,12 @@ namespace NetFabric.Hyperlinq.UnitTests { - public abstract partial class ValueEnumerableTestsBase + public abstract class TestsBase where TEnumerable : struct - where TSkipEnumerable : struct - where TTakeEnumerable : struct { protected readonly Func createInstance; - protected ValueEnumerableTestsBase(Func createInstance) + protected TestsBase(Func createInstance) => this.createInstance = createInstance; [Theory] @@ -29,7 +27,9 @@ public void MustBeEnumerable(int[] source) // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(source, testRefStructs: false); + .BeEqualTo(source); + + // TODO: test ref structs } protected static Expression SkipExpression(Expression source, Expression count) diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Aggregation.cs similarity index 82% rename from NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs rename to NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Aggregation.cs index 3b9f69e32..8c7b45f11 100644 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Aggregation.cs +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Aggregation.cs @@ -6,7 +6,12 @@ namespace NetFabric.Hyperlinq.UnitTests { - public abstract partial class ValueEnumerableTestsBase + public abstract partial class ValueEnumerableTests< + TEnumerable, + TSkipEnumerable, + TTakeEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> { [Theory] [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] @@ -16,6 +21,7 @@ public void MustHaveCount(int[] source) { // Arrange var wrapped = createInstance(source); + // ReSharper disable once CA1829 var expected = source .Count(); diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Conversion.cs similarity index 97% rename from NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs rename to NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Conversion.cs index 682e65fb5..fe3e80842 100644 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Conversion.cs +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Conversion.cs @@ -7,7 +7,12 @@ namespace NetFabric.Hyperlinq.UnitTests { - public abstract partial class ValueEnumerableTestsBase + public abstract partial class ValueEnumerableTests< + TEnumerable, + TSkipEnumerable, + TTakeEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> { // [Fact] // public void MustHaveAsEnumerable() diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Element.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Element.cs new file mode 100644 index 000000000..a7c4deca8 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Element.cs @@ -0,0 +1,162 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTests< + TEnumerable, + TSkipEnumerable, + TTakeEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> + { + [Theory] + [MemberData(nameof(TestData.ElementAt), MemberType = typeof(TestData))] + public void MustHaveElementAt(int[] source, int index) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .ElementAt(index); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var indexParameter = Expression.Parameter(typeof(int), "index"); + var expression = ExpressionBuilder.OperationCall( + "ElementAt", + sourceParameter, + new[] { typeof(int) }, + new[] { indexParameter }); + var func = Expression.Lambda>>(expression, sourceParameter, indexParameter).Compile(); + + // Act + var result = func(wrapped, index); + + // Assert + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); + } + + [Theory] + [MemberData(nameof(TestData.ElementAtOutOfRange), MemberType = typeof(TestData))] + public void MustHaveElementAtOutOfRange(int[] source, int index) + { + // Arrange + var wrapped = createInstance(source); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var indexParameter = Expression.Parameter(typeof(int), "index"); + var expression = ExpressionBuilder.OperationCall( + "ElementAt", + sourceParameter, + new[] { typeof(int) }, + new[] { indexParameter }); + var func = Expression.Lambda>>(expression, sourceParameter, indexParameter).Compile(); + + // Act + var result = func(wrapped, index); + + // Assert + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsNone); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + public void MustHaveFirstEmpty(int[] source) + { + // Arrange + var wrapped = createInstance(source); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall( + "First", + sourceParameter); + var func = Expression.Lambda>>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsNone); + } + + [Theory] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveFirstNonEmpty(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .First(); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall( + "First", + sourceParameter); + var func = Expression.Lambda>>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); + } + + [Theory] + [MemberData(nameof(TestData.Single), MemberType = typeof(TestData))] + public void MustHaveSingleSingle(int[] source) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Single(); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall( + "Single", + sourceParameter); + var func = Expression.Lambda>>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsSome && option.Value == expected); + } + + [Theory] + [MemberData(nameof(TestData.Empty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.Multiple), MemberType = typeof(TestData))] + public void MustHaveSingleNonSingle(int[] source) + { + // Arrange + var wrapped = createInstance(source); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var expression = ExpressionBuilder.OperationCall( + "Single", + sourceParameter); + var func = Expression.Lambda>>(expression, sourceParameter).Compile(); + + // Act + var result = func(wrapped); + + // Assert + _ = result.Must() + .BeOfType>() + .EvaluateTrue(option => option.IsNone); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Filtering.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Filtering.cs new file mode 100644 index 000000000..247877d7d --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Filtering.cs @@ -0,0 +1,76 @@ +using NetFabric.Assertive; +using System; +using System.Linq; +using System.Linq.Expressions; +using Xunit; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTests< + TEnumerable, + TSkipEnumerable, + TTakeEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> + { + [Theory] + [MemberData(nameof(TestData.PredicateEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateMultiple), MemberType = typeof(TestData))] + public void MustHaveWhere(int[] source, Func predicate) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Where(predicate); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var predicateParameter = Expression.Parameter(typeof(Func), "predicate"); + var expression = ExpressionBuilder.OperationCall( + "Where", + sourceParameter, + new[] { typeof(Func) }, + new[] { predicateParameter }); + var func = Expression.Lambda, TWhereEnumerable>>(expression, sourceParameter, predicateParameter).Compile(); + + // Act + var result = func(wrapped, predicate); + + // Assert + _ = result.Must() + .BeOfType() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.PredicateAtEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.PredicateAtMultiple), MemberType = typeof(TestData))] + public void MustHaveWhereAt(int[] source, Func predicate) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Where(predicate); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var predicateParameter = Expression.Parameter(typeof(Func), "predicate"); + var expression = ExpressionBuilder.OperationCall( + "Where", + sourceParameter, + new[] { typeof(Func) }, + new[] { predicateParameter }); + var func = Expression.Lambda, TWhereAtEnumerable>>(expression, sourceParameter, predicateParameter).Compile(); + + // Act + var result = func(wrapped, predicate); + + // Assert + _ = result.Must() + .BeOfType() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Partitioning.cs similarity index 57% rename from NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs rename to NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Partitioning.cs index 063b851b5..d0bfa9ebc 100644 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.Partitioning.cs +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.Partitioning.cs @@ -6,7 +6,10 @@ namespace NetFabric.Hyperlinq.UnitTests { - public abstract partial class ValueEnumerableTestsBase + public abstract partial class ValueEnumerableTests< + TEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> { [Theory] [MemberData(nameof(TestData.Skip_Skip), MemberType = typeof(TestData))] @@ -30,7 +33,7 @@ public void SkipSkipMustSucceed(int[] source, int count1, int count2) // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); + .BeEqualTo(expected); } [Theory] @@ -55,7 +58,7 @@ public void TakeTakeMustSucceed(int[] source, int count1, int count2) // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); + .BeEqualTo(expected); } @@ -83,8 +86,68 @@ public void SkipTakeMustSucceed(int[] source, int count1, int count2) // Assert _ = result.Must() .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); + .BeEqualTo(expected); } } -} \ No newline at end of file + + public abstract partial class ValueEnumerableTests< + TEnumerable, + TSkipEnumerable, + TTakeEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> + { + [Theory] + [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] + public void MustHaveSkip(int[] source, int count) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Skip(count); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var countParameter = Expression.Parameter(typeof(int), "count"); + var expression = SkipExpression(sourceParameter, countParameter); + var func = Expression.Lambda>(expression, sourceParameter, countParameter).Compile(); + + // Act + var result = func(wrapped, count); + + // Assert + _ = result.Must() + .BeOfType() + .BeEnumerableOf() + .BeEqualTo(expected); + } + + [Theory] + [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] + [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] + public void MustHaveTake(int[] source, int count) + { + // Arrange + var wrapped = createInstance(source); + var expected = source + .Take(count); + + var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); + var countParameter = Expression.Parameter(typeof(int), "count"); + var expression = TakeExpression(sourceParameter, countParameter); + var func = Expression.Lambda>(expression, sourceParameter, countParameter).Compile(); + + // Act + var result = func(wrapped, count); + + // Assert + _ = result.Must() + .BeOfType() + .BeEnumerableOf() + .BeEqualTo(expected); + } + } +} diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.cs new file mode 100644 index 000000000..7134b5319 --- /dev/null +++ b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTests.cs @@ -0,0 +1,43 @@ +using System; + +namespace NetFabric.Hyperlinq.UnitTests +{ + public abstract partial class ValueEnumerableTests< + TEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> + : ValueEnumerableTests< + TEnumerable, + TEnumerable, + TEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> + where TEnumerable : struct + where TWhereEnumerable : struct + where TWhereAtEnumerable : struct + { + protected ValueEnumerableTests(Func createInstance) + : base(createInstance) + { + } + } + + public abstract partial class ValueEnumerableTests< + TEnumerable, + TSkipEnumerable, + TTakeEnumerable, + TWhereEnumerable, + TWhereAtEnumerable> + : TestsBase + where TEnumerable : struct + where TSkipEnumerable : struct + where TTakeEnumerable : struct + where TWhereEnumerable : struct + where TWhereAtEnumerable : struct + { + protected ValueEnumerableTests(Func createInstance) + : base(createInstance) + { + } + } +} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs deleted file mode 100644 index a93d9ccd6..000000000 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'1.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace NetFabric.Hyperlinq.UnitTests -{ - public abstract partial class ValueEnumerableTestsBase - : ValueEnumerableTestsBase - where TEnumerable : struct - { - protected ValueEnumerableTestsBase(Func createInstance) - : base(createInstance) - { - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs deleted file mode 100644 index d6cc61079..000000000 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Element.cs +++ /dev/null @@ -1,61 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using System.Linq.Expressions; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests -{ - public abstract partial class ValueEnumerableTestsBase - { - [Theory] - [MemberData(nameof(TestData.ElementAt), MemberType = typeof(TestData))] - public void MustHaveElementAt(int[] source, int index) - { - // Arrange - var wrapped = createInstance(source); - var expected = source - .ElementAt(index); - - var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); - var indexParameter = Expression.Parameter(typeof(int), "index"); - var expression = ExpressionBuilder.OperationCall( - "ElementAt", - sourceParameter, - new[] { typeof(int) }, - new[] { indexParameter }); - var func = Expression.Lambda>>(expression, sourceParameter, indexParameter).Compile(); - - // Act - var result = func(wrapped, index); - - // Assert - _ = result.Must() - .EvaluateTrue(option => option.IsSome && option.Value == expected); - } - - [Theory] - [MemberData(nameof(TestData.ElementAtOutOfRange), MemberType = typeof(TestData))] - public void MustHaveElementAtOutOfRange(int[] source, int index) - { - // Arrange - var wrapped = createInstance(source); - - var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); - var indexParameter = Expression.Parameter(typeof(int), "index"); - var expression = ExpressionBuilder.OperationCall( - "ElementAt", - sourceParameter, - new[] { typeof(int) }, - new[] { indexParameter }); - var func = Expression.Lambda>>(expression, sourceParameter, indexParameter).Compile(); - - // Act - var result = func(wrapped, index); - - // Assert - _ = result.Must() - .EvaluateTrue(option => option.IsNone); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs b/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs deleted file mode 100644 index 0527c021e..000000000 --- a/NetFabric.Hyperlinq.UnitTests/ValueEnumerableTestsBase'4.Partitioning.cs +++ /dev/null @@ -1,61 +0,0 @@ -using NetFabric.Assertive; -using System; -using System.Linq; -using System.Linq.Expressions; -using Xunit; - -namespace NetFabric.Hyperlinq.UnitTests -{ - public abstract partial class ValueEnumerableTestsBase - { - [Theory] - [MemberData(nameof(TestData.SkipEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.SkipMultiple), MemberType = typeof(TestData))] - public void MustHaveSkip(int[] source, int count) - { - // Arrange - var wrapped = createInstance(source); - var expected = source - .Skip(count); - - var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); - var countParameter = Expression.Parameter(typeof(int), "count"); - var expression = SkipExpression(sourceParameter, countParameter); - var func = Expression.Lambda>(expression, sourceParameter, countParameter).Compile(); - - // Act - var result = func(wrapped, count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - } - - [Theory] - [MemberData(nameof(TestData.TakeEmpty), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeSingle), MemberType = typeof(TestData))] - [MemberData(nameof(TestData.TakeMultiple), MemberType = typeof(TestData))] - public void MustHaveTake(int[] source, int count) - { - // Arrange - var wrapped = createInstance(source); - var expected = source - .Take(count); - - var sourceParameter = Expression.Parameter(typeof(TEnumerable), "source"); - var countParameter = Expression.Parameter(typeof(int), "count"); - var expression = TakeExpression(sourceParameter, countParameter); - var func = Expression.Lambda>(expression, sourceParameter, countParameter).Compile(); - - // Act - var result = func(wrapped, count); - - // Assert - _ = result.Must() - .BeEnumerableOf() - .BeEqualTo(expected, testRefStructs: false); - } - } -} \ No newline at end of file diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs index 377e42c14..1bff45bed 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlyMemory.cs @@ -27,16 +27,16 @@ public readonly partial struct MemoryValueEnumerable internal MemoryValueEnumerable(ReadOnlyMemory source) => this.source = source; - public readonly int Count + public int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => source.Length; } - public readonly TSource this[int index] + public ref readonly TSource this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source.Span[index]; + get => ref source.Span[index]; } TSource IReadOnlyList.this[int index] => source.Span[index]; @@ -50,14 +50,17 @@ TSource IList.this[int index] } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SpanEnumerator GetEnumerator() + public SpanEnumerator GetEnumerator() => new(source.Span); - readonly DisposableEnumerator IValueEnumerable.GetEnumerator() + + DisposableEnumerator IValueEnumerable.GetEnumerator() => new(source); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(source); - readonly IEnumerator IEnumerable.GetEnumerator() + + IEnumerator IEnumerable.GetEnumerator() // ReSharper disable once HeapView.BoxingAllocation => new DisposableEnumerator(source); @@ -236,28 +239,6 @@ public MemoryDistinctEnumerable Distinct(IEqualityComparer? co => source.Distinct(comparer); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs index 575fe47f4..673298b2f 100644 --- a/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs +++ b/NetFabric.Hyperlinq/Conversion/AsValueEnumerable/AsValueEnumerable.ReadOnlySpan.cs @@ -24,20 +24,20 @@ public readonly ref partial struct SpanValueEnumerable internal SpanValueEnumerable(ReadOnlySpan source) => this.source = source; - public readonly int Count + public int Count { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => source.Length; } - public readonly TSource this[int index] + public ref readonly TSource this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => source[index]; + get => ref source[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public readonly SpanEnumerator GetEnumerator() + public SpanEnumerator GetEnumerator() => new(source); #region Aggregation diff --git a/NetFabric.Hyperlinq/Filtering/Where/Where/Where.ReadOnlyMemory.cs b/NetFabric.Hyperlinq/Filtering/Where/Where/Where.ReadOnlyMemory.cs index 5588a7dbb..297220d76 100644 --- a/NetFabric.Hyperlinq/Filtering/Where/Where/Where.ReadOnlyMemory.cs +++ b/NetFabric.Hyperlinq/Filtering/Where/Where/Where.ReadOnlyMemory.cs @@ -224,28 +224,6 @@ public Dictionary ToDictionary source.Span.ToDictionary(keySelector, elementSelector, comparer, predicate); #endregion - - public bool SequenceEqual(IEnumerable other, IEqualityComparer? comparer = default) - { - comparer ??= EqualityComparer.Default; - - var enumerator = GetEnumerator(); - using var otherEnumerator = other.GetEnumerator(); - while (true) - { - var thisEnded = !enumerator.MoveNext(); - var otherEnded = !otherEnumerator.MoveNext(); - - if (thisEnded != otherEnded) - return false; - - if (thisEnded) - return true; - - if (!comparer.Equals(enumerator.Current, otherEnumerator.Current)) - return false; - } - } } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj b/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj index c250a4296..fb6e98061 100644 --- a/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj +++ b/NetFabric.Hyperlinq/NetFabric.Hyperlinq.csproj @@ -60,7 +60,7 @@ all runtime; build; native; contentfiles; analyzers - + all runtime; build; native; contentfiles; analyzers