Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
/ corefx Public archive

LINQ ToArray, ToList, ToDictionary unit tests #1692

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/System.Linq/tests/Helpers/TestCollection.cs
Original file line number Diff line number Diff line change
@@ -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<T> : ICollection<T>
{
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<T> GetEnumerator() { return ((IEnumerable<T>)Items).GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); }
}
}
18 changes: 18 additions & 0 deletions src/System.Linq/tests/Helpers/TestEnumerable.cs
Original file line number Diff line number Diff line change
@@ -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<T> : IEnumerable<T>
{
public T[] Items = new T[0];
public TestEnumerable(T[] items) { Items = items; }

public IEnumerator<T> GetEnumerator() { return ((IEnumerable<T>)Items).GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); }
}
}
20 changes: 20 additions & 0 deletions src/System.Linq/tests/Helpers/TestReadOnlyCollection.cs
Original file line number Diff line number Diff line change
@@ -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<T> : IReadOnlyCollection<T>
{
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<T> GetEnumerator() { return ((IEnumerable<T>)Items).GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return Items.GetEnumerator(); }
}
}
6 changes: 6 additions & 0 deletions src/System.Linq/tests/System.Linq.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<Compile Include="CachedEnumerator.cs" />
<Compile Include="EnumerableTests.cs" />
<Compile Include="EmptyEnumerable.cs" />
<Compile Include="Helpers\TestCollection.cs" />
<Compile Include="Helpers\TestEnumerable.cs" />
<Compile Include="Helpers\TestReadOnlyCollection.cs" />
<Compile Include="Performance\CastPerf.cs" />
<Compile Include="Performance\LinqPerformanceCore.cs" />
<Compile Include="Performance\OrderByThenByPerf.cs" />
Expand All @@ -30,6 +33,9 @@
<Compile Include="Performance\WhereSelectPerf.cs" />
<Compile Include="Performance\ToArrayToListToDictionaryPerf.cs" />
<Compile Include="WhereTests.cs" />
<Compile Include="ToArrayTests.cs" />
<Compile Include="ToDictionaryTests.cs" />
<Compile Include="ToListTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\System.Linq.csproj">
Expand Down
157 changes: 157 additions & 0 deletions src/System.Linq/tests/ToArrayTests.cs
Original file line number Diff line number Diff line change
@@ -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<byte>
{
public long MaxSize = 2 * (long)int.MaxValue;
public IEnumerator<byte> GetEnumerator()
{
for (long i = 0; i < MaxSize; i++) yield return (byte)1;
}
IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); }
}

/// <summary>
/// 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.
/// </summary>
private class GrowingAfterCountReadCollection : TestCollection<int>
{
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>(T[] items, Action<T[]> validation)
{
validation(Enumerable.ToArray(items));
validation(Enumerable.ToArray(new List<T>(items)));
validation(new TestEnumerable<T>(items).ToArray());
validation(new TestReadOnlyCollection<T>(items).ToArray());
validation(new TestCollection<T>(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<int> source = new TestCollection<int>(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<ArgumentNullException>(() => source.ToArray());
}


// Later this behaviour can be changed
[Fact]
[ActiveIssue(1561)]
public void ToArray_UseCopyToWithICollection()
{
TestCollection<int> source = new TestCollection<int>(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<Exception>(() => { largeSeq.ToArray(); });
Assert.True(thrownException.GetType() == typeof(OverflowException) || thrownException.GetType() == typeof(OutOfMemoryException));
}
}
}
Loading