diff --git a/.editorconfig b/.editorconfig index bf62f14a8..49a41778a 100644 --- a/.editorconfig +++ b/.editorconfig @@ -87,6 +87,10 @@ dotnet_diagnostic.IDE0055.severity = suggestion # IDE0046: Convert to conditional expression dotnet_diagnostic.IDE0046.severity = suggestion +# Dispose things need disposing +# CA2000: Dispose objects before losing scope +dotnet_diagnostic.CA2000.severity = error + # CA1510: Use 'ArgumentNullException.ThrowIfNull' instead of explicitly throwing a new exception instance # TODO: Remove post https://github.com/morelinq/MoreLINQ/issues/903 dotnet_diagnostic.CA1510.severity = suggestion diff --git a/MoreLinq.Test/AggregateRightTest.cs b/MoreLinq.Test/AggregateRightTest.cs index 7ecd4825e..959609670 100644 --- a/MoreLinq.Test/AggregateRightTest.cs +++ b/MoreLinq.Test/AggregateRightTest.cs @@ -18,6 +18,8 @@ namespace MoreLinq.Test { using NUnit.Framework; + using System; + using System.Collections.Generic; [TestFixture] public class AggregateRightTest @@ -27,28 +29,31 @@ public class AggregateRightTest [Test] public void AggregateRightWithEmptySequence() { - Assert.That(() => new int[0].AggregateRight((a, b) => a + b), - Throws.InvalidOperationException); + using var ts = TestingSequence.Of(); + Assert.That( + () => ts.AggregateRight((a, b) => a + b), + Throws.InvalidOperationException); } [Test] public void AggregateRightFuncIsNotInvokedOnSingleElementSequence() { - const int value = 1; + using var ts = TestingSequence.Of(1); + var result = ts.AggregateRight(BreakingFunc.Of()); - var result = new[] { value }.AggregateRight(BreakingFunc.Of()); - - Assert.That(result, Is.EqualTo(value)); + Assert.That(result, Is.EqualTo(1)); } - [TestCase(SourceKind.BreakingList)] - [TestCase(SourceKind.BreakingReadOnlyList)] - [TestCase(SourceKind.Sequence)] - public void AggregateRight(SourceKind sourceKind) - { - var enumerable = Enumerable.Range(1, 5).Select(x => x.ToInvariantString()).ToSourceKind(sourceKind); + public static IEnumerable AggregateRightSource => + Enumerable.Range(1, 5) + .Select(x => x.ToInvariantString()) + .ToTestData(SourceKinds.Sequence.Concat(SourceKinds.List)); - var result = enumerable.AggregateRight((a, b) => $"({a}+{b})"); + [TestCaseSource(nameof(AggregateRightSource))] + public void AggregateRight(IEnumerable sequence) + { + using var d = sequence as IDisposable; + var result = sequence.AggregateRight((a, b) => $"({a}+{b})"); Assert.That(result, Is.EqualTo("(1+(2+(3+(4+5))))")); } @@ -60,24 +65,30 @@ public void AggregateRight(SourceKind sourceKind) [TestCase(true)] public void AggregateRightSeedWithEmptySequence(object defaultValue) { - Assert.That(new int[0].AggregateRight(defaultValue, (_, b) => b), Is.EqualTo(defaultValue)); + using var ts = TestingSequence.Of(); + var result = ts.AggregateRight(defaultValue, (_, b) => b); + + Assert.That(result, Is.EqualTo(defaultValue)); } [Test] public void AggregateRightSeedFuncIsNotInvokedOnEmptySequence() { - const int value = 1; + using var ts = TestingSequence.Of(); + var result = ts.AggregateRight(1, BreakingFunc.Of()); - var result = new int[0].AggregateRight(value, BreakingFunc.Of()); - - Assert.That(result, Is.EqualTo(value)); + Assert.That(result, Is.EqualTo(1)); } - [Test] - public void AggregateRightSeed() + public static IEnumerable AggregateRightSeedSource => + Enumerable.Range(1, 4) + .ToTestData(SourceKinds.Sequence.Concat(SourceKinds.List)); + + [TestCaseSource(nameof(AggregateRightSeedSource))] + public void AggregateRightSeed(IEnumerable sequence) { - var result = Enumerable.Range(1, 4) - .AggregateRight("5", (a, b) => $"({a}+{b})"); + using var d = sequence as IDisposable; + var result = sequence.AggregateRight("5", (a, b) => $"({a}+{b})"); Assert.That(result, Is.EqualTo("(1+(2+(3+(4+5))))")); } @@ -89,14 +100,16 @@ public void AggregateRightSeed() [TestCase(true)] public void AggregateRightResultorWithEmptySequence(object defaultValue) { - Assert.That(new int[0].AggregateRight(defaultValue, (_, b) => b, a => a == defaultValue), Is.EqualTo(true)); + using var ts = TestingSequence.Of(); + var result = ts.AggregateRight(defaultValue, (_, b) => b, a => a == defaultValue); + Assert.That(result, Is.EqualTo(true)); } - [Test] - public void AggregateRightResultor() + [TestCaseSource(nameof(AggregateRightSeedSource))] + public void AggregateRightResultor(IEnumerable sequence) { - var result = Enumerable.Range(1, 4) - .AggregateRight("5", (a, b) => $"({a}+{b})", a => a.Length); + using var d = sequence as IDisposable; + var result = sequence.AggregateRight("5", (a, b) => $"({a}+{b})", a => a.Length); Assert.That(result, Is.EqualTo("(1+(2+(3+(4+5))))".Length)); } diff --git a/MoreLinq.Test/AppendTest.cs b/MoreLinq.Test/AppendTest.cs index 0398a5658..67e177a8e 100644 --- a/MoreLinq.Test/AppendTest.cs +++ b/MoreLinq.Test/AppendTest.cs @@ -17,6 +17,7 @@ namespace MoreLinq.Test { + using System; using System.Collections.Generic; using NUnit.Framework; using static MoreLinq.Extensions.AppendExtension; @@ -60,10 +61,11 @@ public void AppendIsLazyInHeadSequence() #endregion [TestCaseSource(nameof(ContactManySource))] - public void AppendMany(int[] head, int[] tail) + public void AppendMany(IEnumerable head, IEnumerable tail, IEnumerable expected) { - tail.Aggregate(head.AsEnumerable(), (xs, x) => xs.Append(x)) - .AssertSequenceEqual(head.Concat(tail)); + using var d = head as IDisposable; + tail.Aggregate(head, (xs, x) => xs.Append(x)) + .AssertSequenceEqual(expected); } public static IEnumerable ContactManySource => @@ -75,14 +77,16 @@ from y in Enumerable.Range(1, 20 - x) Tail = Enumerable.Range(x + 1, y).ToArray(), } into e - select new TestCaseData(e.Head, - e.Tail).SetName("Head = [" + string.Join(", ", e.Head) + "], " + - "Tail = [" + string.Join(", ", e.Tail) + "]"); + select new TestCaseData(e.Head.AsTestingSequence(), + e.Tail, + e.Head.Concat(e.Tail)) + .SetName("Head = [" + string.Join(", ", e.Head) + "], " + + "Tail = [" + string.Join(", ", e.Tail) + "]"); [Test] public void AppendWithSharedSource() { - var first = new[] { 1 }.Append(2); + using var first = new TestingSequence([1, 2], maxEnumerations: 2); var second = first.Append(3).Append(4); var third = first.Append(4).Append(8); diff --git a/MoreLinq.Test/TestingSequence.cs b/MoreLinq.Test/TestingSequence.cs index 479459a9b..d2073d164 100644 --- a/MoreLinq.Test/TestingSequence.cs +++ b/MoreLinq.Test/TestingSequence.cs @@ -55,6 +55,31 @@ public enum Options AllowRepeatedDisposals = 0x2, AllowRepeatedMoveNexts = 0x4, } + + internal static IEnumerable ToTestData( + this IEnumerable input, + IEnumerable kinds) + { + var list = input.ToList(); + foreach (var k in kinds) + { + var sequence = list.ToTestKind(k); + var data = new TestCaseData(sequence) + .SetName($"{{m}}({k}[{string.Join(", ", list)}]"); + yield return data; + } + } + + internal static IEnumerable ToTestKind(this IEnumerable input, SourceKind kind) => + kind switch + { + SourceKind.Sequence => new TestingSequence(input, Options.None, maxEnumerations: 2), + SourceKind.BreakingList => new BreakingList(input.ToList()), + SourceKind.BreakingReadOnlyList => new BreakingReadOnlyList(input.ToList()), + SourceKind.BreakingCollection => new BreakingCollection(input.ToList()), + SourceKind.BreakingReadOnlyCollection => new BreakingReadOnlyCollection(input.ToList()), + _ => throw new InvalidOperationException("Unknown SourceKind"), + }; } /// @@ -71,7 +96,7 @@ sealed class TestingSequence : IEnumerable, IDisposable int _disposedCount; int _enumerationCount; - internal TestingSequence(IEnumerable sequence, Options options, int maxEnumerations) + internal TestingSequence(IEnumerable sequence, Options options = Options.None, int maxEnumerations = 1) { _sequence = sequence; _maxEnumerations = maxEnumerations;