From 624b6b13e5a556d8bce671f15a49ba1847638ce4 Mon Sep 17 00:00:00 2001 From: ikopylov Date: Sun, 10 May 2015 20:31:15 +0300 Subject: [PATCH 1/2] LINQ ToArray, ToList, ToDictionary unit tests --- .../tests/System.Linq.Tests.csproj | 1 + .../tests/ToArrayToListToDictionaryTests.cs | 469 ++++++++++++++++++ src/System.Linq/tests/project.json | 3 +- 3 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 src/System.Linq/tests/ToArrayToListToDictionaryTests.cs diff --git a/src/System.Linq/tests/System.Linq.Tests.csproj b/src/System.Linq/tests/System.Linq.Tests.csproj index 809a88eaff18..7414d61d81d5 100644 --- a/src/System.Linq/tests/System.Linq.Tests.csproj +++ b/src/System.Linq/tests/System.Linq.Tests.csproj @@ -30,6 +30,7 @@ + diff --git a/src/System.Linq/tests/ToArrayToListToDictionaryTests.cs b/src/System.Linq/tests/ToArrayToListToDictionaryTests.cs new file mode 100644 index 000000000000..0327bf2c35f5 --- /dev/null +++ b/src/System.Linq/tests/ToArrayToListToDictionaryTests.cs @@ -0,0 +1,469 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + + +namespace System.Linq.Tests +{ + public class ToArrayToListToDictionaryTests + { + #region ============= Helper classes ============= + + private class EnumerableCollectionTest : IEnumerable + { + public T[] Items = new T[0]; + public EnumerableCollectionTest(T[] items) { Items = items; } + + public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } + } + private class ReadOnlyCollectionTest : IReadOnlyCollection + { + public T[] Items = new T[0]; + public int CountTouched = 0; + public ReadOnlyCollectionTest(T[] items) { Items = items; } + + public int Count { get { CountTouched++; return Items.Length; } } + public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } + } + private class CollectionTest : ICollection + { + public T[] Items = new T[0]; + public int CountTouched = 0; + public int CopyToTouched = 0; + public CollectionTest(T[] items) { Items = items; } + + public virtual int Count { get { CountTouched++; return Items.Length; } } + public bool IsReadOnly { get { return false; } } + public void Add(T item) { throw new NotImplementedException(); } + public void Clear() { throw new NotImplementedException(); } + public bool Contains(T item) { return Items.Contains(item); } + public bool Remove(T item) { throw new NotImplementedException(); } + public void CopyTo(T[] array, int arrayIndex) { CopyToTouched++; Items.CopyTo(array, arrayIndex); } + public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } + } + + private class LargeSequenceTest: IEnumerable + { + public long MaxSize = 2 * (long)int.MaxValue; + public IEnumerator GetEnumerator() + { + for (long i = 0; i < MaxSize; i++) yield return (byte)1; + } + IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } + } + + /// + /// Emulation of async collection change + /// + private class AsyncCollectionTest : CollectionTest + { + public AsyncCollectionTest(int[] items) : base(items) { } + + public override int Count + { + get + { + var result = base.Count; + Array.Resize(ref Items, Items.Length + 1); + return result; + } + } + } + + private class CustomComparer : IEqualityComparer + { + public bool Equals(T x, T y) { return EqualityComparer.Default.Equals(x, y); } + public int GetHashCode(T obj) { return EqualityComparer.Default.GetHashCode(obj); } + } + + #endregion + + + #region ============= ToArray ============= + + [Fact] + public void ToArray_AlwaysCreateACopy() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5 }; + int[] resultArray = sourceArray.ToArray(); + + Assert.NotSame(sourceArray, resultArray); + Assert.Equal(sourceArray, resultArray); + } + + + private void RunToArrayOnAllCollectionTypes(T[] items, Action validation) + { + validation(Enumerable.ToArray(items)); + validation(Enumerable.ToArray(new List(items))); + validation(new EnumerableCollectionTest(items).ToArray()); + validation(new ReadOnlyCollectionTest(items).ToArray()); + validation(new CollectionTest(items).ToArray()); + } + + + [Fact] + public void ToArray_WorkWithEmptyCollection() + { + RunToArrayOnAllCollectionTypes(new int[0], + resultArray => + { + Assert.NotNull(resultArray); + Assert.Equal(0, resultArray.Length); + }); + } + + [Fact] + public void ToArray_ProduceCorrectArray() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + RunToArrayOnAllCollectionTypes(sourceArray, + resultArray => + { + Assert.Equal(sourceArray.Length, resultArray.Length); + Assert.Equal(sourceArray, resultArray); + }); + + string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; + RunToArrayOnAllCollectionTypes(sourceStringArray, + resultStringArray => + { + Assert.Equal(sourceStringArray.Length, resultStringArray.Length); + for (int i = 0; i < sourceStringArray.Length; i++) + Assert.Same(sourceStringArray[i], resultStringArray[i]); + }); + } + + + [Fact] + public void ToArray_TouchCountWithICollection() + { + CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); + var resultArray = source.ToArray(); + + Assert.Equal(source, resultArray); + Assert.Equal(1, source.CountTouched); + } + + + [Fact] + public void ToArray_ThrowArgumentNullExceptionWhenSourceIsNull() + { + int[] source = null; + Assert.Throws(() => source.ToArray()); + } + + + // Later this behaviour can be changed + [Fact] + public void ToArray_UseCopyToWithICollection() + { + CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); + var resultArray = source.ToArray(); + + Assert.Equal(source, resultArray); + Assert.Equal(1, source.CopyToTouched); + } + + + // Currently not passed + //[Fact] + public void ToArray_WorkWhenCountChangedAsynchronously() + { + AsyncCollectionTest source = new AsyncCollectionTest(new int[] { 1, 2, 3, 4 }); + var resultArray = source.ToArray(); + + Assert.True(resultArray.Length >= 4); + Assert.Equal(1, resultArray[0]); + Assert.Equal(2, resultArray[0]); + Assert.Equal(3, resultArray[0]); + Assert.Equal(4, resultArray[0]); + } + + + //[Fact] + public void ToArray_FailOnExtremelyLargeCollection() + { + LargeSequenceTest largeSeq = new LargeSequenceTest(); + Assert.ThrowsAny(() => { largeSeq.ToArray(); }); + } + + + #endregion + + + #region ============= ToList ============= + + [Fact] + public void ToList_AlwaysCreateACopy() + { + List sourceList = new List() { 1, 2, 3, 4, 5 }; + List resultList = sourceList.ToList(); + + Assert.NotSame(sourceList, resultList); + Assert.Equal(sourceList, resultList); + } + + + private void RunToListOnAllCollectionTypes(T[] items, Action> validation) + { + validation(Enumerable.ToList(items)); + validation(Enumerable.ToList(new List(items))); + validation(new EnumerableCollectionTest(items).ToList()); + validation(new ReadOnlyCollectionTest(items).ToList()); + validation(new CollectionTest(items).ToList()); + } + + + [Fact] + public void ToList_WorkWithEmptyCollection() + { + RunToListOnAllCollectionTypes(new int[0], + resultList => + { + Assert.NotNull(resultList); + Assert.Equal(0, resultList.Count); + }); + } + + [Fact] + public void ToList_ProduceCorrectList() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + RunToListOnAllCollectionTypes(sourceArray, + resultList => + { + Assert.Equal(sourceArray.Length, resultList.Count); + Assert.Equal(sourceArray, resultList); + }); + + string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; + RunToListOnAllCollectionTypes(sourceStringArray, + resultStringList => + { + Assert.Equal(sourceStringArray.Length, resultStringList.Count); + for (int i = 0; i < sourceStringArray.Length; i++) + Assert.Same(sourceStringArray[i], resultStringList[i]); + }); + } + + + [Fact] + public void ToList_TouchCountWithICollection() + { + CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); + var resultList = source.ToList(); + + Assert.Equal(source, resultList); + Assert.Equal(1, source.CountTouched); + } + + + [Fact] + public void ToList_ThrowArgumentNullExceptionWhenSourceIsNull() + { + int[] source = null; + Assert.Throws(() => source.ToList()); + } + + + // Later this behaviour can be changed + [Fact] + public void ToList_UseCopyToWithICollection() + { + CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); + var resultList = source.ToList(); + + Assert.Equal(source, resultList); + Assert.Equal(1, source.CopyToTouched); + } + + + // Currently not passed + //[Fact] + public void ToList_WorkWhenCountChangedAsynchronously() + { + AsyncCollectionTest source = new AsyncCollectionTest(new int[] { 1, 2, 3, 4 }); + var resultList = source.ToList(); + + Assert.True(resultList.Count >= 4); + Assert.Equal(1, resultList[0]); + Assert.Equal(2, resultList[0]); + Assert.Equal(3, resultList[0]); + Assert.Equal(4, resultList[0]); + } + + + + #endregion + + + #region ============= ToDictionary ============= + + [Fact] + public void ToDictionary_AlwaysCreateACopy() + { + Dictionary source = new Dictionary() { { 1, 1 }, { 2, 2 }, { 3, 3 } }; + Dictionary result = source.ToDictionary(key => key.Key, val => val.Value); + + Assert.NotSame(source, result); + Assert.Equal(source, result); + } + + + private void RunToDictionaryOnAllCollectionTypes(T[] items, Action> validation) + { + validation(Enumerable.ToDictionary(items, key => key)); + validation(Enumerable.ToDictionary(items, key => key, value => value)); + validation(Enumerable.ToDictionary(new List(items), key => key)); + validation(Enumerable.ToDictionary(new List(items), key => key, value => value)); + validation(new EnumerableCollectionTest(items).ToDictionary(key => key)); + validation(new EnumerableCollectionTest(items).ToDictionary(key => key, value => value)); + validation(new ReadOnlyCollectionTest(items).ToDictionary(key => key)); + validation(new ReadOnlyCollectionTest(items).ToDictionary(key => key, value => value)); + validation(new CollectionTest(items).ToDictionary(key => key)); + validation(new CollectionTest(items).ToDictionary(key => key, value => value)); + } + + + [Fact] + public void ToDictionary_WorkWithEmptyCollection() + { + RunToDictionaryOnAllCollectionTypes(new int[0], + resultDictionary => + { + Assert.NotNull(resultDictionary); + Assert.Equal(0, resultDictionary.Count); + }); + } + + + [Fact] + public void ToDictionary_ProduceCorrectDictionary() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + RunToDictionaryOnAllCollectionTypes(sourceArray, + resultDictionary => + { + Assert.Equal(sourceArray.Length, resultDictionary.Count); + Assert.Equal(sourceArray, resultDictionary.Keys); + Assert.Equal(sourceArray, resultDictionary.Values); + }); + + string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; + RunToDictionaryOnAllCollectionTypes(sourceStringArray, + resultDictionary => + { + Assert.Equal(sourceStringArray.Length, resultDictionary.Count); + for (int i = 0; i < sourceStringArray.Length; i++) + Assert.Same(sourceStringArray[i], resultDictionary[sourceStringArray[i]]); + }); + } + + + + [Fact] + public void ToDictionary_PassCustomComparer() + { + CustomComparer comparer = new CustomComparer(); + CollectionTest collection = new CollectionTest(new int[] { 1, 2, 3, 4, 5, 6 }); + + Dictionary result1 = collection.ToDictionary(key => key, comparer); + Assert.Same(comparer, result1.Comparer); + + Dictionary result2 = collection.ToDictionary(key => key, val => val, comparer); + Assert.Same(comparer, result2.Comparer); + } + + [Fact] + public void ToDictionary_UseDefaultComparerOnNull() + { + CustomComparer comparer = null; + CollectionTest collection = new CollectionTest(new int[] { 1, 2, 3, 4, 5, 6 }); + + Dictionary result1 = collection.ToDictionary(key => key, comparer); + Assert.Same(EqualityComparer.Default, result1.Comparer); + + Dictionary result2 = collection.ToDictionary(key => key, val => val, comparer); + Assert.Same(EqualityComparer.Default, result2.Comparer); + } + + [Fact] + public void ToDictionary_KeyValueSelectorsWork() + { + CollectionTest collection = new CollectionTest(new int[] { 1, 2, 3, 4, 5, 6 }); + + Dictionary result = collection.ToDictionary(key => key + 10, val => val + 100); + + Assert.Equal(collection.Items.Select(o => o + 10), result.Keys); + Assert.Equal(collection.Items.Select(o => o + 100), result.Values); + } + + + [Fact] + public void ToDictionary_ThrowArgumentNullExceptionWhenSourceIsNull() + { + int[] source = null; + Assert.Throws(() => source.ToDictionary(key => key)); + } + + + [Fact] + public void ToDictionary_ThrowArgumentNullExceptionWhenKeySelectorIsNull() + { + int[] source = new int[0]; + Func keySelector = null; + Assert.Throws(() => source.ToDictionary(keySelector)); + } + + [Fact] + public void ToDictionary_ThrowArgumentNullExceptionWhenValueSelectorIsNull() + { + int[] source = new int[0]; + Func keySelector = key => key; + Func valueSelector = null; + Assert.Throws(() => source.ToDictionary(keySelector, valueSelector)); + } + + + [Fact] + public void ToDictionary_KeySelectorThrowException() + { + int[] source = new int[] { 1, 2, 3 }; + Func keySelector = key => + { + if (key == 1) + throw new InvalidOperationException(); + return key; + }; + + + Assert.Throws(() => source.ToDictionary(keySelector)); + } + + [Fact] + public void ToDictionary_ValueSelectorThrowException() + { + int[] source = new int[] { 1, 2, 3 }; + Func keySelector = key => key; + Func valueSelector = value => + { + if (value == 1) + throw new InvalidOperationException(); + return value; + }; + + Assert.Throws(() => source.ToDictionary(keySelector, valueSelector)); + } + + + #endregion + } +} diff --git a/src/System.Linq/tests/project.json b/src/System.Linq/tests/project.json index 7cf60a47035b..25d3ca18fda3 100644 --- a/src/System.Linq/tests/project.json +++ b/src/System.Linq/tests/project.json @@ -8,7 +8,8 @@ "xunit": "2.0.0-beta5-build2785", "xunit.abstractions.netcore": "1.0.0-prerelease", "xunit.assert": "2.0.0-beta5-build2785", - "xunit.core.netcore": "1.0.1-prerelease" + "xunit.core.netcore": "1.0.1-prerelease", + "xunit.netcore.extensions": "1.0.0-prerelease" }, "frameworks": { "dnxcore50": {} From 282695422e94eb13f3ca9d1c0b98ea238876c916 Mon Sep 17 00:00:00 2001 From: ikopylov Date: Mon, 11 May 2015 19:03:10 +0300 Subject: [PATCH 2/2] LINQ ToArray, ToList, ToDictionary tests were updated based on code review --- .../tests/Helpers/TestCollection.cs | 27 + .../tests/Helpers/TestEnumerable.cs | 18 + .../tests/Helpers/TestReadOnlyCollection.cs | 20 + .../tests/System.Linq.Tests.csproj | 7 +- src/System.Linq/tests/ToArrayTests.cs | 157 ++++++ .../tests/ToArrayToListToDictionaryTests.cs | 469 ------------------ src/System.Linq/tests/ToDictionaryTests.cs | 196 ++++++++ src/System.Linq/tests/ToListTests.cs | 136 +++++ 8 files changed, 560 insertions(+), 470 deletions(-) create mode 100644 src/System.Linq/tests/Helpers/TestCollection.cs create mode 100644 src/System.Linq/tests/Helpers/TestEnumerable.cs create mode 100644 src/System.Linq/tests/Helpers/TestReadOnlyCollection.cs create mode 100644 src/System.Linq/tests/ToArrayTests.cs delete mode 100644 src/System.Linq/tests/ToArrayToListToDictionaryTests.cs create mode 100644 src/System.Linq/tests/ToDictionaryTests.cs create mode 100644 src/System.Linq/tests/ToListTests.cs diff --git a/src/System.Linq/tests/Helpers/TestCollection.cs b/src/System.Linq/tests/Helpers/TestCollection.cs new file mode 100644 index 000000000000..b03c04789621 --- /dev/null +++ b/src/System.Linq/tests/Helpers/TestCollection.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Linq.Tests.Helpers +{ + public class TestCollection : ICollection + { + public T[] Items = new T[0]; + public int CountTouched = 0; + public int CopyToTouched = 0; + public TestCollection(T[] items) { Items = items; } + + public virtual int Count { get { CountTouched++; return Items.Length; } } + public bool IsReadOnly { get { return false; } } + public void Add(T item) { throw new NotImplementedException(); } + public void Clear() { throw new NotImplementedException(); } + public bool Contains(T item) { return Items.Contains(item); } + public bool Remove(T item) { throw new NotImplementedException(); } + public void CopyTo(T[] array, int arrayIndex) { CopyToTouched++; Items.CopyTo(array, arrayIndex); } + public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } + } +} diff --git a/src/System.Linq/tests/Helpers/TestEnumerable.cs b/src/System.Linq/tests/Helpers/TestEnumerable.cs new file mode 100644 index 000000000000..bc9423e937c4 --- /dev/null +++ b/src/System.Linq/tests/Helpers/TestEnumerable.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Linq.Tests.Helpers +{ + public class TestEnumerable : IEnumerable + { + public T[] Items = new T[0]; + public TestEnumerable(T[] items) { Items = items; } + + public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } + } +} diff --git a/src/System.Linq/tests/Helpers/TestReadOnlyCollection.cs b/src/System.Linq/tests/Helpers/TestReadOnlyCollection.cs new file mode 100644 index 000000000000..16f6c21f1b4e --- /dev/null +++ b/src/System.Linq/tests/Helpers/TestReadOnlyCollection.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Linq.Tests.Helpers +{ + public class TestReadOnlyCollection : IReadOnlyCollection + { + public T[] Items = new T[0]; + public int CountTouched = 0; + public TestReadOnlyCollection(T[] items) { Items = items; } + + public int Count { get { CountTouched++; return Items.Length; } } + public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } + IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } + } +} diff --git a/src/System.Linq/tests/System.Linq.Tests.csproj b/src/System.Linq/tests/System.Linq.Tests.csproj index 7414d61d81d5..e716afed7e10 100644 --- a/src/System.Linq/tests/System.Linq.Tests.csproj +++ b/src/System.Linq/tests/System.Linq.Tests.csproj @@ -21,6 +21,9 @@ + + + @@ -30,7 +33,9 @@ - + + + diff --git a/src/System.Linq/tests/ToArrayTests.cs b/src/System.Linq/tests/ToArrayTests.cs new file mode 100644 index 000000000000..cb20c9781952 --- /dev/null +++ b/src/System.Linq/tests/ToArrayTests.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Tests.Helpers; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Linq.Tests +{ + public class ToArrayTests + { + private class TestLargeSequence : IEnumerable + { + public long MaxSize = 2 * (long)int.MaxValue; + public IEnumerator GetEnumerator() + { + for (long i = 0; i < MaxSize; i++) yield return (byte)1; + } + IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } + } + + /// + /// Emulation of async collection change. + /// It adds a new element to the sequence each time the Count property touched, + /// so the further call of CopyTo method will fail. + /// + private class GrowingAfterCountReadCollection : TestCollection + { + public GrowingAfterCountReadCollection(int[] items) : base(items) { } + + public override int Count + { + get + { + var result = base.Count; + Array.Resize(ref Items, Items.Length + 1); + return result; + } + } + } + + // ===================== + + + [Fact] + public void ToArray_AlwaysCreateACopy() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5 }; + int[] resultArray = sourceArray.ToArray(); + + Assert.NotSame(sourceArray, resultArray); + Assert.Equal(sourceArray, resultArray); + } + + + private void RunToArrayOnAllCollectionTypes(T[] items, Action validation) + { + validation(Enumerable.ToArray(items)); + validation(Enumerable.ToArray(new List(items))); + validation(new TestEnumerable(items).ToArray()); + validation(new TestReadOnlyCollection(items).ToArray()); + validation(new TestCollection(items).ToArray()); + } + + + [Fact] + public void ToArray_WorkWithEmptyCollection() + { + RunToArrayOnAllCollectionTypes(new int[0], + resultArray => + { + Assert.NotNull(resultArray); + Assert.Equal(0, resultArray.Length); + }); + } + + [Fact] + public void ToArray_ProduceCorrectArray() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + RunToArrayOnAllCollectionTypes(sourceArray, + resultArray => + { + Assert.Equal(sourceArray.Length, resultArray.Length); + Assert.Equal(sourceArray, resultArray); + }); + + string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; + RunToArrayOnAllCollectionTypes(sourceStringArray, + resultStringArray => + { + Assert.Equal(sourceStringArray.Length, resultStringArray.Length); + for (int i = 0; i < sourceStringArray.Length; i++) + Assert.Same(sourceStringArray[i], resultStringArray[i]); + }); + } + + + [Fact] + public void ToArray_TouchCountWithICollection() + { + TestCollection source = new TestCollection(new int[] { 1, 2, 3, 4 }); + var resultArray = source.ToArray(); + + Assert.Equal(source, resultArray); + Assert.Equal(1, source.CountTouched); + } + + + [Fact] + public void ToArray_ThrowArgumentNullExceptionWhenSourceIsNull() + { + int[] source = null; + Assert.Throws(() => source.ToArray()); + } + + + // Later this behaviour can be changed + [Fact] + [ActiveIssue(1561)] + public void ToArray_UseCopyToWithICollection() + { + TestCollection source = new TestCollection(new int[] { 1, 2, 3, 4 }); + var resultArray = source.ToArray(); + + Assert.Equal(source, resultArray); + Assert.Equal(1, source.CopyToTouched); + } + + + [Fact] + [ActiveIssue(1561)] + public void ToArray_WorkWhenCountChangedAsynchronously() + { + GrowingAfterCountReadCollection source = new GrowingAfterCountReadCollection(new int[] { 1, 2, 3, 4 }); + var resultArray = source.ToArray(); + + Assert.True(resultArray.Length >= 4); + Assert.Equal(1, resultArray[0]); + Assert.Equal(2, resultArray[0]); + Assert.Equal(3, resultArray[0]); + Assert.Equal(4, resultArray[0]); + } + + + [Fact] + [OuterLoop] + public void ToArray_FailOnExtremelyLargeCollection() + { + TestLargeSequence largeSeq = new TestLargeSequence(); + var thrownException = Assert.ThrowsAny(() => { largeSeq.ToArray(); }); + Assert.True(thrownException.GetType() == typeof(OverflowException) || thrownException.GetType() == typeof(OutOfMemoryException)); + } + } +} diff --git a/src/System.Linq/tests/ToArrayToListToDictionaryTests.cs b/src/System.Linq/tests/ToArrayToListToDictionaryTests.cs deleted file mode 100644 index 0327bf2c35f5..000000000000 --- a/src/System.Linq/tests/ToArrayToListToDictionaryTests.cs +++ /dev/null @@ -1,469 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; - - -namespace System.Linq.Tests -{ - public class ToArrayToListToDictionaryTests - { - #region ============= Helper classes ============= - - private class EnumerableCollectionTest : IEnumerable - { - public T[] Items = new T[0]; - public EnumerableCollectionTest(T[] items) { Items = items; } - - public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } - } - private class ReadOnlyCollectionTest : IReadOnlyCollection - { - public T[] Items = new T[0]; - public int CountTouched = 0; - public ReadOnlyCollectionTest(T[] items) { Items = items; } - - public int Count { get { CountTouched++; return Items.Length; } } - public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } - } - private class CollectionTest : ICollection - { - public T[] Items = new T[0]; - public int CountTouched = 0; - public int CopyToTouched = 0; - public CollectionTest(T[] items) { Items = items; } - - public virtual int Count { get { CountTouched++; return Items.Length; } } - public bool IsReadOnly { get { return false; } } - public void Add(T item) { throw new NotImplementedException(); } - public void Clear() { throw new NotImplementedException(); } - public bool Contains(T item) { return Items.Contains(item); } - public bool Remove(T item) { throw new NotImplementedException(); } - public void CopyTo(T[] array, int arrayIndex) { CopyToTouched++; Items.CopyTo(array, arrayIndex); } - public IEnumerator GetEnumerator() { return ((IEnumerable)Items).GetEnumerator(); } - IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); } - } - - private class LargeSequenceTest: IEnumerable - { - public long MaxSize = 2 * (long)int.MaxValue; - public IEnumerator GetEnumerator() - { - for (long i = 0; i < MaxSize; i++) yield return (byte)1; - } - IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } - } - - /// - /// Emulation of async collection change - /// - private class AsyncCollectionTest : CollectionTest - { - public AsyncCollectionTest(int[] items) : base(items) { } - - public override int Count - { - get - { - var result = base.Count; - Array.Resize(ref Items, Items.Length + 1); - return result; - } - } - } - - private class CustomComparer : IEqualityComparer - { - public bool Equals(T x, T y) { return EqualityComparer.Default.Equals(x, y); } - public int GetHashCode(T obj) { return EqualityComparer.Default.GetHashCode(obj); } - } - - #endregion - - - #region ============= ToArray ============= - - [Fact] - public void ToArray_AlwaysCreateACopy() - { - int[] sourceArray = new int[] { 1, 2, 3, 4, 5 }; - int[] resultArray = sourceArray.ToArray(); - - Assert.NotSame(sourceArray, resultArray); - Assert.Equal(sourceArray, resultArray); - } - - - private void RunToArrayOnAllCollectionTypes(T[] items, Action validation) - { - validation(Enumerable.ToArray(items)); - validation(Enumerable.ToArray(new List(items))); - validation(new EnumerableCollectionTest(items).ToArray()); - validation(new ReadOnlyCollectionTest(items).ToArray()); - validation(new CollectionTest(items).ToArray()); - } - - - [Fact] - public void ToArray_WorkWithEmptyCollection() - { - RunToArrayOnAllCollectionTypes(new int[0], - resultArray => - { - Assert.NotNull(resultArray); - Assert.Equal(0, resultArray.Length); - }); - } - - [Fact] - public void ToArray_ProduceCorrectArray() - { - int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; - RunToArrayOnAllCollectionTypes(sourceArray, - resultArray => - { - Assert.Equal(sourceArray.Length, resultArray.Length); - Assert.Equal(sourceArray, resultArray); - }); - - string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; - RunToArrayOnAllCollectionTypes(sourceStringArray, - resultStringArray => - { - Assert.Equal(sourceStringArray.Length, resultStringArray.Length); - for (int i = 0; i < sourceStringArray.Length; i++) - Assert.Same(sourceStringArray[i], resultStringArray[i]); - }); - } - - - [Fact] - public void ToArray_TouchCountWithICollection() - { - CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); - var resultArray = source.ToArray(); - - Assert.Equal(source, resultArray); - Assert.Equal(1, source.CountTouched); - } - - - [Fact] - public void ToArray_ThrowArgumentNullExceptionWhenSourceIsNull() - { - int[] source = null; - Assert.Throws(() => source.ToArray()); - } - - - // Later this behaviour can be changed - [Fact] - public void ToArray_UseCopyToWithICollection() - { - CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); - var resultArray = source.ToArray(); - - Assert.Equal(source, resultArray); - Assert.Equal(1, source.CopyToTouched); - } - - - // Currently not passed - //[Fact] - public void ToArray_WorkWhenCountChangedAsynchronously() - { - AsyncCollectionTest source = new AsyncCollectionTest(new int[] { 1, 2, 3, 4 }); - var resultArray = source.ToArray(); - - Assert.True(resultArray.Length >= 4); - Assert.Equal(1, resultArray[0]); - Assert.Equal(2, resultArray[0]); - Assert.Equal(3, resultArray[0]); - Assert.Equal(4, resultArray[0]); - } - - - //[Fact] - public void ToArray_FailOnExtremelyLargeCollection() - { - LargeSequenceTest largeSeq = new LargeSequenceTest(); - Assert.ThrowsAny(() => { largeSeq.ToArray(); }); - } - - - #endregion - - - #region ============= ToList ============= - - [Fact] - public void ToList_AlwaysCreateACopy() - { - List sourceList = new List() { 1, 2, 3, 4, 5 }; - List resultList = sourceList.ToList(); - - Assert.NotSame(sourceList, resultList); - Assert.Equal(sourceList, resultList); - } - - - private void RunToListOnAllCollectionTypes(T[] items, Action> validation) - { - validation(Enumerable.ToList(items)); - validation(Enumerable.ToList(new List(items))); - validation(new EnumerableCollectionTest(items).ToList()); - validation(new ReadOnlyCollectionTest(items).ToList()); - validation(new CollectionTest(items).ToList()); - } - - - [Fact] - public void ToList_WorkWithEmptyCollection() - { - RunToListOnAllCollectionTypes(new int[0], - resultList => - { - Assert.NotNull(resultList); - Assert.Equal(0, resultList.Count); - }); - } - - [Fact] - public void ToList_ProduceCorrectList() - { - int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; - RunToListOnAllCollectionTypes(sourceArray, - resultList => - { - Assert.Equal(sourceArray.Length, resultList.Count); - Assert.Equal(sourceArray, resultList); - }); - - string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; - RunToListOnAllCollectionTypes(sourceStringArray, - resultStringList => - { - Assert.Equal(sourceStringArray.Length, resultStringList.Count); - for (int i = 0; i < sourceStringArray.Length; i++) - Assert.Same(sourceStringArray[i], resultStringList[i]); - }); - } - - - [Fact] - public void ToList_TouchCountWithICollection() - { - CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); - var resultList = source.ToList(); - - Assert.Equal(source, resultList); - Assert.Equal(1, source.CountTouched); - } - - - [Fact] - public void ToList_ThrowArgumentNullExceptionWhenSourceIsNull() - { - int[] source = null; - Assert.Throws(() => source.ToList()); - } - - - // Later this behaviour can be changed - [Fact] - public void ToList_UseCopyToWithICollection() - { - CollectionTest source = new CollectionTest(new int[] { 1, 2, 3, 4 }); - var resultList = source.ToList(); - - Assert.Equal(source, resultList); - Assert.Equal(1, source.CopyToTouched); - } - - - // Currently not passed - //[Fact] - public void ToList_WorkWhenCountChangedAsynchronously() - { - AsyncCollectionTest source = new AsyncCollectionTest(new int[] { 1, 2, 3, 4 }); - var resultList = source.ToList(); - - Assert.True(resultList.Count >= 4); - Assert.Equal(1, resultList[0]); - Assert.Equal(2, resultList[0]); - Assert.Equal(3, resultList[0]); - Assert.Equal(4, resultList[0]); - } - - - - #endregion - - - #region ============= ToDictionary ============= - - [Fact] - public void ToDictionary_AlwaysCreateACopy() - { - Dictionary source = new Dictionary() { { 1, 1 }, { 2, 2 }, { 3, 3 } }; - Dictionary result = source.ToDictionary(key => key.Key, val => val.Value); - - Assert.NotSame(source, result); - Assert.Equal(source, result); - } - - - private void RunToDictionaryOnAllCollectionTypes(T[] items, Action> validation) - { - validation(Enumerable.ToDictionary(items, key => key)); - validation(Enumerable.ToDictionary(items, key => key, value => value)); - validation(Enumerable.ToDictionary(new List(items), key => key)); - validation(Enumerable.ToDictionary(new List(items), key => key, value => value)); - validation(new EnumerableCollectionTest(items).ToDictionary(key => key)); - validation(new EnumerableCollectionTest(items).ToDictionary(key => key, value => value)); - validation(new ReadOnlyCollectionTest(items).ToDictionary(key => key)); - validation(new ReadOnlyCollectionTest(items).ToDictionary(key => key, value => value)); - validation(new CollectionTest(items).ToDictionary(key => key)); - validation(new CollectionTest(items).ToDictionary(key => key, value => value)); - } - - - [Fact] - public void ToDictionary_WorkWithEmptyCollection() - { - RunToDictionaryOnAllCollectionTypes(new int[0], - resultDictionary => - { - Assert.NotNull(resultDictionary); - Assert.Equal(0, resultDictionary.Count); - }); - } - - - [Fact] - public void ToDictionary_ProduceCorrectDictionary() - { - int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; - RunToDictionaryOnAllCollectionTypes(sourceArray, - resultDictionary => - { - Assert.Equal(sourceArray.Length, resultDictionary.Count); - Assert.Equal(sourceArray, resultDictionary.Keys); - Assert.Equal(sourceArray, resultDictionary.Values); - }); - - string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; - RunToDictionaryOnAllCollectionTypes(sourceStringArray, - resultDictionary => - { - Assert.Equal(sourceStringArray.Length, resultDictionary.Count); - for (int i = 0; i < sourceStringArray.Length; i++) - Assert.Same(sourceStringArray[i], resultDictionary[sourceStringArray[i]]); - }); - } - - - - [Fact] - public void ToDictionary_PassCustomComparer() - { - CustomComparer comparer = new CustomComparer(); - CollectionTest collection = new CollectionTest(new int[] { 1, 2, 3, 4, 5, 6 }); - - Dictionary result1 = collection.ToDictionary(key => key, comparer); - Assert.Same(comparer, result1.Comparer); - - Dictionary result2 = collection.ToDictionary(key => key, val => val, comparer); - Assert.Same(comparer, result2.Comparer); - } - - [Fact] - public void ToDictionary_UseDefaultComparerOnNull() - { - CustomComparer comparer = null; - CollectionTest collection = new CollectionTest(new int[] { 1, 2, 3, 4, 5, 6 }); - - Dictionary result1 = collection.ToDictionary(key => key, comparer); - Assert.Same(EqualityComparer.Default, result1.Comparer); - - Dictionary result2 = collection.ToDictionary(key => key, val => val, comparer); - Assert.Same(EqualityComparer.Default, result2.Comparer); - } - - [Fact] - public void ToDictionary_KeyValueSelectorsWork() - { - CollectionTest collection = new CollectionTest(new int[] { 1, 2, 3, 4, 5, 6 }); - - Dictionary result = collection.ToDictionary(key => key + 10, val => val + 100); - - Assert.Equal(collection.Items.Select(o => o + 10), result.Keys); - Assert.Equal(collection.Items.Select(o => o + 100), result.Values); - } - - - [Fact] - public void ToDictionary_ThrowArgumentNullExceptionWhenSourceIsNull() - { - int[] source = null; - Assert.Throws(() => source.ToDictionary(key => key)); - } - - - [Fact] - public void ToDictionary_ThrowArgumentNullExceptionWhenKeySelectorIsNull() - { - int[] source = new int[0]; - Func keySelector = null; - Assert.Throws(() => source.ToDictionary(keySelector)); - } - - [Fact] - public void ToDictionary_ThrowArgumentNullExceptionWhenValueSelectorIsNull() - { - int[] source = new int[0]; - Func keySelector = key => key; - Func valueSelector = null; - Assert.Throws(() => source.ToDictionary(keySelector, valueSelector)); - } - - - [Fact] - public void ToDictionary_KeySelectorThrowException() - { - int[] source = new int[] { 1, 2, 3 }; - Func keySelector = key => - { - if (key == 1) - throw new InvalidOperationException(); - return key; - }; - - - Assert.Throws(() => source.ToDictionary(keySelector)); - } - - [Fact] - public void ToDictionary_ValueSelectorThrowException() - { - int[] source = new int[] { 1, 2, 3 }; - Func keySelector = key => key; - Func valueSelector = value => - { - if (value == 1) - throw new InvalidOperationException(); - return value; - }; - - Assert.Throws(() => source.ToDictionary(keySelector, valueSelector)); - } - - - #endregion - } -} diff --git a/src/System.Linq/tests/ToDictionaryTests.cs b/src/System.Linq/tests/ToDictionaryTests.cs new file mode 100644 index 000000000000..4f09851fdd4a --- /dev/null +++ b/src/System.Linq/tests/ToDictionaryTests.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Tests.Helpers; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Linq.Tests +{ + public class ToDictionaryTests + { + private class CustomComparer : IEqualityComparer + { + public bool Equals(T x, T y) { return EqualityComparer.Default.Equals(x, y); } + public int GetHashCode(T obj) { return EqualityComparer.Default.GetHashCode(obj); } + } + + // ===================== + + + [Fact] + public void ToDictionary_AlwaysCreateACopy() + { + Dictionary source = new Dictionary() { { 1, 1 }, { 2, 2 }, { 3, 3 } }; + Dictionary result = source.ToDictionary(key => key.Key, val => val.Value); + + Assert.NotSame(source, result); + Assert.Equal(source, result); + } + + + private void RunToDictionaryOnAllCollectionTypes(T[] items, Action> validation) + { + validation(Enumerable.ToDictionary(items, key => key)); + validation(Enumerable.ToDictionary(items, key => key, value => value)); + validation(Enumerable.ToDictionary(new List(items), key => key)); + validation(Enumerable.ToDictionary(new List(items), key => key, value => value)); + validation(new TestEnumerable(items).ToDictionary(key => key)); + validation(new TestEnumerable(items).ToDictionary(key => key, value => value)); + validation(new TestReadOnlyCollection(items).ToDictionary(key => key)); + validation(new TestReadOnlyCollection(items).ToDictionary(key => key, value => value)); + validation(new TestCollection(items).ToDictionary(key => key)); + validation(new TestCollection(items).ToDictionary(key => key, value => value)); + } + + + [Fact] + public void ToDictionary_WorkWithEmptyCollection() + { + RunToDictionaryOnAllCollectionTypes(new int[0], + resultDictionary => + { + Assert.NotNull(resultDictionary); + Assert.Equal(0, resultDictionary.Count); + }); + } + + + [Fact] + public void ToDictionary_ProduceCorrectDictionary() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + RunToDictionaryOnAllCollectionTypes(sourceArray, + resultDictionary => + { + Assert.Equal(sourceArray.Length, resultDictionary.Count); + Assert.Equal(sourceArray, resultDictionary.Keys); + Assert.Equal(sourceArray, resultDictionary.Values); + }); + + string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; + RunToDictionaryOnAllCollectionTypes(sourceStringArray, + resultDictionary => + { + Assert.Equal(sourceStringArray.Length, resultDictionary.Count); + for (int i = 0; i < sourceStringArray.Length; i++) + Assert.Same(sourceStringArray[i], resultDictionary[sourceStringArray[i]]); + }); + } + + + + [Fact] + public void ToDictionary_PassCustomComparer() + { + CustomComparer comparer = new CustomComparer(); + TestCollection collection = new TestCollection(new int[] { 1, 2, 3, 4, 5, 6 }); + + Dictionary result1 = collection.ToDictionary(key => key, comparer); + Assert.Same(comparer, result1.Comparer); + + Dictionary result2 = collection.ToDictionary(key => key, val => val, comparer); + Assert.Same(comparer, result2.Comparer); + } + + [Fact] + public void ToDictionary_UseDefaultComparerOnNull() + { + CustomComparer comparer = null; + TestCollection collection = new TestCollection(new int[] { 1, 2, 3, 4, 5, 6 }); + + Dictionary result1 = collection.ToDictionary(key => key, comparer); + Assert.Same(EqualityComparer.Default, result1.Comparer); + + Dictionary result2 = collection.ToDictionary(key => key, val => val, comparer); + Assert.Same(EqualityComparer.Default, result2.Comparer); + } + + [Fact] + public void ToDictionary_KeyValueSelectorsWork() + { + TestCollection collection = new TestCollection(new int[] { 1, 2, 3, 4, 5, 6 }); + + Dictionary result = collection.ToDictionary(key => key + 10, val => val + 100); + + Assert.Equal(collection.Items.Select(o => o + 10), result.Keys); + Assert.Equal(collection.Items.Select(o => o + 100), result.Values); + } + + + [Fact] + public void ToDictionary_ThrowArgumentNullExceptionWhenSourceIsNull() + { + int[] source = null; + Assert.Throws(() => source.ToDictionary(key => key)); + } + + + [Fact] + public void ToDictionary_ThrowArgumentNullExceptionWhenKeySelectorIsNull() + { + int[] source = new int[0]; + Func keySelector = null; + Assert.Throws(() => source.ToDictionary(keySelector)); + } + + [Fact] + public void ToDictionary_ThrowArgumentNullExceptionWhenValueSelectorIsNull() + { + int[] source = new int[0]; + Func keySelector = key => key; + Func valueSelector = null; + Assert.Throws(() => source.ToDictionary(keySelector, valueSelector)); + } + + + [Fact] + public void ToDictionary_KeySelectorThrowException() + { + int[] source = new int[] { 1, 2, 3 }; + Func keySelector = key => + { + if (key == 1) + throw new InvalidOperationException(); + return key; + }; + + + Assert.Throws(() => source.ToDictionary(keySelector)); + } + + [Fact] + public void ToDictionary_ThrowWhenKeySelectorReturnNull() + { + int[] source = new int[] { 1, 2, 3 }; + Func keySelector = key => null; + + Assert.Throws(() => source.ToDictionary(keySelector)); + } + + [Fact] + public void ToDictionary_ThrowWhenKeySelectorReturnSameValueTwice() + { + int[] source = new int[] { 1, 2, 3 }; + Func keySelector = key => 1; + + Assert.Throws(() => source.ToDictionary(keySelector)); + } + + [Fact] + public void ToDictionary_ValueSelectorThrowException() + { + int[] source = new int[] { 1, 2, 3 }; + Func keySelector = key => key; + Func valueSelector = value => + { + if (value == 1) + throw new InvalidOperationException(); + return value; + }; + + Assert.Throws(() => source.ToDictionary(keySelector, valueSelector)); + } + } +} diff --git a/src/System.Linq/tests/ToListTests.cs b/src/System.Linq/tests/ToListTests.cs new file mode 100644 index 000000000000..24f5dccea24f --- /dev/null +++ b/src/System.Linq/tests/ToListTests.cs @@ -0,0 +1,136 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Tests.Helpers; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace System.Linq.Tests +{ + public class ToListTests + { + /// + /// Emulation of async collection change. + /// It adds a new element to the sequence each time the Count property touched, + /// so the further call of CopyTo method will fail. + /// + private class GrowingAfterCountReadCollection : TestCollection + { + public GrowingAfterCountReadCollection(int[] items) : base(items) { } + + public override int Count + { + get + { + var result = base.Count; + Array.Resize(ref Items, Items.Length + 1); + return result; + } + } + } + + // ============================ + + + [Fact] + public void ToList_AlwaysCreateACopy() + { + List sourceList = new List() { 1, 2, 3, 4, 5 }; + List resultList = sourceList.ToList(); + + Assert.NotSame(sourceList, resultList); + Assert.Equal(sourceList, resultList); + } + + + private void RunToListOnAllCollectionTypes(T[] items, Action> validation) + { + validation(Enumerable.ToList(items)); + validation(Enumerable.ToList(new List(items))); + validation(new TestEnumerable(items).ToList()); + validation(new TestReadOnlyCollection(items).ToList()); + validation(new TestCollection(items).ToList()); + } + + + [Fact] + public void ToList_WorkWithEmptyCollection() + { + RunToListOnAllCollectionTypes(new int[0], + resultList => + { + Assert.NotNull(resultList); + Assert.Equal(0, resultList.Count); + }); + } + + [Fact] + public void ToList_ProduceCorrectList() + { + int[] sourceArray = new int[] { 1, 2, 3, 4, 5, 6, 7 }; + RunToListOnAllCollectionTypes(sourceArray, + resultList => + { + Assert.Equal(sourceArray.Length, resultList.Count); + Assert.Equal(sourceArray, resultList); + }); + + string[] sourceStringArray = new string[] { "1", "2", "3", "4", "5", "6", "7", "8" }; + RunToListOnAllCollectionTypes(sourceStringArray, + resultStringList => + { + Assert.Equal(sourceStringArray.Length, resultStringList.Count); + for (int i = 0; i < sourceStringArray.Length; i++) + Assert.Same(sourceStringArray[i], resultStringList[i]); + }); + } + + + [Fact] + public void ToList_TouchCountWithICollection() + { + TestCollection source = new TestCollection(new int[] { 1, 2, 3, 4 }); + var resultList = source.ToList(); + + Assert.Equal(source, resultList); + Assert.Equal(1, source.CountTouched); + } + + + [Fact] + public void ToList_ThrowArgumentNullExceptionWhenSourceIsNull() + { + int[] source = null; + Assert.Throws(() => source.ToList()); + } + + + // Later this behaviour can be changed + [Fact] + [ActiveIssue(1561)] + public void ToList_UseCopyToWithICollection() + { + TestCollection source = new TestCollection(new int[] { 1, 2, 3, 4 }); + var resultList = source.ToList(); + + Assert.Equal(source, resultList); + Assert.Equal(1, source.CopyToTouched); + } + + + [Fact] + [ActiveIssue(1561)] + public void ToList_WorkWhenCountChangedAsynchronously() + { + GrowingAfterCountReadCollection source = new GrowingAfterCountReadCollection(new int[] { 1, 2, 3, 4 }); + var resultList = source.ToList(); + + Assert.True(resultList.Count >= 4); + Assert.Equal(1, resultList[0]); + Assert.Equal(2, resultList[0]); + Assert.Equal(3, resultList[0]); + Assert.Equal(4, resultList[0]); + } + } +}