diff --git a/MoreLinq.Test/Collection.cs b/MoreLinq.Test/Collection.cs new file mode 100644 index 000000000..2c9c7c69e --- /dev/null +++ b/MoreLinq.Test/Collection.cs @@ -0,0 +1,50 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2023 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq.Test +{ + using System.Collections; + using System.Collections.Generic; + + /// + /// This class is a wrapper around a that only implement . + /// + sealed class Collection : ICollection + { + readonly IList _list; + + public Collection(IList list) => _list = list; + + public int Count => _list.Count; + + public bool IsReadOnly => false; + + public void Add(T item) => _list.Add(item); + + public void Clear() => _list.Clear(); + + public bool Contains(T item) => _list.Contains(item); + + public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex); + + public IEnumerator GetEnumerator() => _list.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_list).GetEnumerator(); + + public bool Remove(T item) => _list.Remove(item); + } +} diff --git a/MoreLinq.Test/EndsWithTest.cs b/MoreLinq.Test/EndsWithTest.cs index 108980360..1a638e00c 100644 --- a/MoreLinq.Test/EndsWithTest.cs +++ b/MoreLinq.Test/EndsWithTest.cs @@ -17,56 +17,50 @@ namespace MoreLinq.Test { + using System.Collections; using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; using NUnit.Framework; - [TestFixture] + [TestFixture(SourceKind.Sequence, SourceKind.Sequence)] + [TestFixture(SourceKind.Sequence, SourceKind.Collection)] + [TestFixture(SourceKind.Sequence, SourceKind.List)] + [TestFixture(SourceKind.Collection, SourceKind.Sequence)] + [TestFixture(SourceKind.Collection, SourceKind.Collection)] + [TestFixture(SourceKind.Collection, SourceKind.List)] + [TestFixture(SourceKind.List, SourceKind.Sequence)] + [TestFixture(SourceKind.List, SourceKind.Collection)] + [TestFixture(SourceKind.List, SourceKind.List)] public class EndsWithTest { + readonly SourceKind _firstSourceKind; + readonly SourceKind _secondSourceKind; + + public EndsWithTest(SourceKind firstSourceKind, SourceKind secondSourceKind) + { + _firstSourceKind = firstSourceKind; + _secondSourceKind = secondSourceKind; + } + + [TestCase(new int[0], new int[0], ExpectedResult = true)] + [TestCase(new int[0], new[] { 1, 2, 3 }, ExpectedResult = false)] + [TestCase(new[] { 1, 2, 3 }, new int[0], ExpectedResult = true)] [TestCase(new[] { 1, 2, 3 }, new[] { 2, 3 }, ExpectedResult = true)] [TestCase(new[] { 1, 2, 3 }, new[] { 1, 2, 3 }, ExpectedResult = true)] [TestCase(new[] { 1, 2, 3 }, new[] { 0, 1, 2, 3 }, ExpectedResult = false)] public bool EndsWithWithIntegers(IEnumerable first, IEnumerable second) { - return first.EndsWith(second); - } - - [TestCase(new[] { '1', '2', '3' }, new[] { '2', '3' }, ExpectedResult = true)] - [TestCase(new[] { '1', '2', '3' }, new[] { '1', '2', '3' }, ExpectedResult = true)] - [TestCase(new[] { '1', '2', '3' }, new[] { '0', '1', '2', '3' }, ExpectedResult = false)] - public bool EndsWithWithChars(IEnumerable first, IEnumerable second) - { - return first.EndsWith(second); + return first.ToSourceKind(_firstSourceKind).EndsWith(second.ToSourceKind(_secondSourceKind)); } + [TestCase("", "", ExpectedResult = true)] + [TestCase("", "1", ExpectedResult = false)] + [TestCase("1", "", ExpectedResult = true)] [TestCase("123", "23", ExpectedResult = true)] [TestCase("123", "123", ExpectedResult = true)] [TestCase("123", "0123", ExpectedResult = false)] public bool EndsWithWithStrings(string first, string second) { - // Conflict with String.EndsWith(), which has precedence in this case - return MoreEnumerable.EndsWith(first, second); - } - - [Test] - public void EndsWithReturnsTrueIfBothEmpty() - { - Assert.That(new int[0].EndsWith(new int[0]), Is.True); - } - - [Test] - public void EndsWithReturnsFalseIfOnlyFirstIsEmpty() - { - Assert.That(new int[0].EndsWith(new[] { 1, 2, 3 }), Is.False); - } - - [TestCase("", "", ExpectedResult = true)] - [TestCase("1", "", ExpectedResult = true)] - public bool EndsWithReturnsTrueIfSecondIsEmpty(string first, string second) - { - // Conflict with String.EndsWith(), which has precedence in this case - return MoreEnumerable.EndsWith(first, second); + return first.ToSourceKind(_firstSourceKind).EndsWith(second.ToSourceKind(_secondSourceKind)); } [Test] @@ -78,17 +72,23 @@ public void EndsWithDisposesBothSequenceEnumerators() _ = first.EndsWith(second); } - [Test] - [SuppressMessage("ReSharper", "RedundantArgumentDefaultValue")] - public void EndsWithUsesSpecifiedEqualityComparerOrDefault() + [TestCaseSource(nameof(EndsWithUsesSpecifiedEqualityComparerOrDefaultTestCases))] + public bool EndsWithUsesSpecifiedEqualityComparerOrDefault(IEqualityComparer? equalityComparer) { - var first = new[] { 1, 2, 3 }; - var second = new[] { 4, 5, 6 }; + var first = new[] { 1, 2, 3 }.ToSourceKind(_firstSourceKind); + var second = new[] { 4, 5, 6 }.ToSourceKind(_secondSourceKind); - Assert.That(first.EndsWith(second), Is.False); - Assert.That(first.EndsWith(second, null), Is.False); - Assert.That(first.EndsWith(second, EqualityComparer.Create(delegate { return false; })), Is.False); - Assert.That(first.EndsWith(second, EqualityComparer.Create(delegate { return true; })), Is.True); + return first.EndsWith(second, equalityComparer); + } + + public static IEnumerable EndsWithUsesSpecifiedEqualityComparerOrDefaultTestCases + { + get + { + yield return new TestCaseData(null).Returns(false); + yield return new TestCaseData(EqualityComparer.Create(delegate { return false; })).Returns(false); + yield return new TestCaseData(EqualityComparer.Create(delegate { return true; })).Returns(true); + } } [TestCase(SourceKind.BreakingCollection)] diff --git a/MoreLinq.Test/TestExtensions.cs b/MoreLinq.Test/TestExtensions.cs index e327c09e8..e0aecd82c 100644 --- a/MoreLinq.Test/TestExtensions.cs +++ b/MoreLinq.Test/TestExtensions.cs @@ -25,6 +25,8 @@ namespace MoreLinq.Test public enum SourceKind { Sequence, + Collection, + List, BreakingList, BreakingReadOnlyList, BreakingCollection, @@ -91,6 +93,8 @@ internal static IEnumerable ToSourceKind(this IEnumerable input, Source sourceKind switch { SourceKind.Sequence => input.Select(x => x), + SourceKind.Collection => new Collection(input.ToList()), + SourceKind.List => input.ToList(), SourceKind.BreakingList => new BreakingList(input.ToList()), SourceKind.BreakingReadOnlyList => new BreakingReadOnlyList(input.ToList()), SourceKind.BreakingCollection => new BreakingCollection(input.ToList()),