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

Commit

Permalink
Merge pull request #1692 from ikopylov/linq_toArray_toList_toDictiona…
Browse files Browse the repository at this point in the history
…ry_tests

LINQ ToArray, ToList, ToDictionary unit tests
  • Loading branch information
stephentoub committed May 11, 2015
2 parents 94c90ba + 2826954 commit a746248
Show file tree
Hide file tree
Showing 8 changed files with 562 additions and 1 deletion.
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 @@ -32,6 +35,9 @@
<Compile Include="RangeTests.cs" />
<Compile Include="RepeatTests.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

0 comments on commit a746248

Please sign in to comment.