using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Threading; using SabreTools.IO.Extensions; using Xunit; namespace SabreTools.IO.Test.Extensions { public class EnumerableExtensionsTests { #region IterateWithAction [Fact] public void IterateWithActionTest() { List source = [1, 2, 3, 4]; int actual = 0; source.IterateWithAction(i => Interlocked.Add(ref actual, i)); Assert.Equal(10, actual); } #endregion #region SafeEnumerate [Fact] public void SafeEnumerate_Empty() { var source = Enumerable.Empty(); var safe = source.SafeEnumerate(); var list = safe.ToList(); Assert.Empty(list); } [Fact] public void SafeEnumerate_Throws() { var source = new List { "a", "ab", "abc" }; var wrapper = new ThrowsEnumerable(source); var safe = wrapper.SafeEnumerate(); var list = safe.ToList(); Assert.Empty(list); } [Fact] public void SafeEnumerate_NoError() { var source = new List { "a", "ab", "abc" }; var safe = source.SafeEnumerate(); var list = safe.ToList(); Assert.Equal(3, list.Count); } [Fact] public void SafeEnumerate_ErrorMid() { var source = new List { "a", "ab", "abc" }; var wrapper = new ErrorEnumerable(source); var safe = wrapper.SafeEnumerate(); var list = safe.ToList(); Assert.Equal(2, list.Count); } [Fact] public void SafeEnumerate_ErrorLast() { var source = new List { "a", "ab", "abc", "abcd" }; var wrapper = new ErrorEnumerable(source); var safe = wrapper.SafeEnumerate(); var list = safe.ToList(); Assert.Equal(2, list.Count); } #endregion /// /// Fake enumerable that uses /// private class ErrorEnumerable : IEnumerable { /// /// Enumerator to use during enumeration /// private readonly ErrorEnumerator _enumerator; public ErrorEnumerable(IEnumerable source) { _enumerator = new ErrorEnumerator(source); } /// public IEnumerator GetEnumerator() => _enumerator; /// IEnumerator IEnumerable.GetEnumerator() => _enumerator; } /// /// Fake enumerator that throws an exception every other item while moving to the next item /// private class ErrorEnumerator : IEnumerator { /// public string Current { get { if (_index == -1) throw new InvalidOperationException(); return _enumerator.Current; } } /// object IEnumerator.Current => Current; /// /// Enumerator from the source enumerable /// private readonly IEnumerator _enumerator; /// /// Enumerators start before the data /// private int _index = -1; public ErrorEnumerator(IEnumerable source) { _enumerator = source.GetEnumerator(); } /// public void Dispose() { } /// public bool MoveNext() { // Move to the next item, if possible bool moved = _enumerator.MoveNext(); if (!moved) return false; // Get the next real item _index++; // Every other move, throw an exception if (_index % 2 == 1) throw new Exception("Access issue for this item in the enumerable"); return true; } /// public void Reset() { _enumerator.Reset(); _index = -1; } } /// /// Fake enumerable that throws an exception for the enumerator /// private class ThrowsEnumerable : IEnumerable { public ThrowsEnumerable(IEnumerable source) { } /// public IEnumerator GetEnumerator() => throw new Exception(); /// IEnumerator IEnumerable.GetEnumerator() => throw new Exception(); } } }