Skip to content

chore: Update System.Linq.Tests tests to .NET 10 preview.2 based code #150

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
94 changes: 77 additions & 17 deletions tests/System.Linq.Tests/Stubs/System.Linq/EnumerableTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ protected static IEnumerable<T> FlipIsCollection<T>(IEnumerable<T> source)
{
return source is ICollection<T> ? ForceNotCollection(source) : new List<T>(source);
}

protected static T[] Repeat<T>(Func<int, T> factory, int count)
{
T[] results = new T[count];
Expand Down Expand Up @@ -320,27 +321,86 @@ protected static IEnumerable<IEnumerable<T>> CreateSources<T>(IEnumerable<T> sou
}
}

// TODO: latest `dotnet/runtime` version supports more test patterns.
protected static List<Func<IEnumerable<T>, IEnumerable<T>>> IdentityTransforms<T>()
protected static IEnumerable<Func<IEnumerable<T>, IEnumerable<T>>> IdentityTransforms<T>()
{
// All of these transforms should take an enumerable and produce
// another enumerable with the same contents.
return new List<Func<IEnumerable<T>, IEnumerable<T>>>
// Various collection types all representing the same source.
List<Func<IEnumerable<T>, IEnumerable<T>>> sources =
[
e => e, // original
e => e.ToArray(), // T[]
e => e.ToList(), // List<T>
e => new ReadOnlyCollection<T>(e.ToArray()), // IList<T> that's not List<T>/T[]
e => new TestCollection<T>(e.ToArray()), // ICollection<T> that's not IList<T>
e => new TestReadOnlyCollection<T>(e.ToArray()), // IReadOnlyCollection<T> that's not ICollection<T>
e => ForceNotCollection(e), // IEnumerable<T> with no other interfaces
];
if (typeof(T) == typeof(char))
{
e => e,
e => e.ToArray(),
e => e.ToList(),
e => e.ToList().Take(int.MaxValue),
sources.Add(e => (IEnumerable<T>)(object)string.Concat((IEnumerable<char>)(object)e)); // string
}

// Various transforms that all yield the same elements as the source.
List<Func<IEnumerable<T>, IEnumerable<T>>> transforms =
[
// Concat
e => e.Concat(ForceNotCollection<T>([])),
e => ForceNotCollection<T>([]).Concat(e),

// Following transforms cause test failure on System.Linq tests with .NET 9
#if NET10_0_OR_GREATER
// Append
e =>
{
T[] values = e.ToArray();
return values.Length == 0 ? [] : values[0..^1].Append(values[^1]);
},

// Prepend
e =>
{
T[] values = e.ToArray();
return values.Length == 0 ? [] : values[1..].Prepend(values[0]);
},

// Reverse
e => e.Reverse().Reverse(),
#endif

// Select
e => e.Select(i => i),
e => e.Select(i => i).Take(int.MaxValue),
e => e.Select(i => i).Where(i => true),

// SelectMany
e => e.SelectMany<T, T>(i => [i]),

// Take
e => e.Take(int.MaxValue),
e => e.TakeLast(int.MaxValue),
e => e.TakeWhile(i => true),

// Skip
e => e.SkipWhile(i => false),

// Where
e => e.Where(i => true),
e => e.Concat(Array.Empty<T>()),
e => e.Concat(ForceNotCollection(Array.Empty<T>())),
e => ForceNotCollection(e),
e => ForceNotCollection(e).Skip(0),
e => new ReadOnlyCollection<T>(e.ToArray()),
};
];

foreach (Func<IEnumerable<T>, IEnumerable<T>> source in sources)
{
// Yield the source itself.
yield return source;

foreach (Func<IEnumerable<T>, IEnumerable<T>> transform in transforms)
{
// Yield a single transform on the source
yield return e => transform(source(e));

foreach (Func<IEnumerable<T>, IEnumerable<T>> transform2 in transforms)
{
// Yield a second transform on the first transform on the source.
yield return e => transform2(transform(source(e)));
}
}
}
}

protected sealed class DelegateIterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>
Expand Down
58 changes: 5 additions & 53 deletions tests/System.Linq.Tests/Stubs/TestData/MinMaxTestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,39 @@

using System.Linq.Tests;

// Original code: https://github.com/dotnet/runtime/blob/v9.0.3/src/libraries/Common/tests/System/Linq/SkipTakeData.cs
// Original code:
// https://github.com/dotnet/runtime/blob/v10.0.0-preview.2.25163.2/src/libraries/System.Linq/tests/MinTests.cs
// https://github.com/dotnet/runtime/blob/v10.0.0-preview.2.25163.2/src/libraries/System.Linq/tests/MaxTests.cs

namespace System.Linq;

// This class is used to share test data between System.Linq/ZLinq tests.
// Note: It need to use `Shuffler.Shuffle` to show indivisual test cases on Test Explorer.
public class MinMaxTestData
{
public static IEnumerable<object[]> Min_AllTypes_TestData()
{
for (int length = 2; length < 65; length++)
{
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (byte)i)), (byte)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (byte)i).ToArray()), (byte)length };

// Unit Tests does +T.One so we should generate data up to one value below sbyte.MaxValue, otherwise the type overflows
if ((length + length) < sbyte.MaxValue)
{
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (sbyte)i)), (sbyte)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (sbyte)i).ToArray()), (sbyte)length };
}

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ushort)i)), (ushort)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ushort)i).ToArray()), (ushort)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (short)i)), (short)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (short)i).ToArray()), (short)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (uint)i)), (uint)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (uint)i).ToArray()), (uint)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (int)i)), (int)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (int)i).ToArray()), (int)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ulong)i)), (ulong)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ulong)i).ToArray()), (ulong)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (long)i)), (long)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (long)i).ToArray()), (long)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (float)i)), (float)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (float)i).ToArray()), (float)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (double)i)), (double)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (double)i).ToArray()), (double)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (decimal)i)), (decimal)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (decimal)i).ToArray()), (decimal)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nuint)i)), (nuint)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nuint)i).ToArray()), (nuint)length };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nint)i)), (nint)length };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nint)i).ToArray()), (nint)length };
}
}

Expand All @@ -63,56 +44,27 @@ public static IEnumerable<object[]> Max_AllTypes_TestData()
for (int length = 2; length < 65; length++)
{
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (byte)i)), (byte)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (byte)i).ToArray()), (byte)(length + length - 1) };

// Unit Tests does +T.One so we should generate data up to one value below sbyte.MaxValue
if ((length + length) < sbyte.MaxValue)
{
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (sbyte)i)), (sbyte)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (sbyte)i).ToArray()), (sbyte)(length + length - 1) };
}

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ushort)i)), (ushort)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ushort)i).ToArray()), (ushort)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (short)i)), (short)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (short)i).ToArray()), (short)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (char)i)), (char)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (char)i).ToArray()), (char)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (uint)i)), (uint)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (uint)i).ToArray()), (uint)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (int)i)), (int)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (int)i).ToArray()), (int)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ulong)i)), (ulong)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (ulong)i).ToArray()), (ulong)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (long)i)), (long)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (long)i).ToArray()), (long)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (float)i)), (float)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (float)i).ToArray()), (float)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (double)i)), (double)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (double)i).ToArray()), (double)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (decimal)i)), (decimal)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (decimal)i).ToArray()), (decimal)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nuint)i)), (nuint)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nuint)i).ToArray()), (nuint)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nint)i)), (nint)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (nint)i).ToArray()), (nint)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (Int128)i)), (Int128)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (Int128)i).ToArray()), (Int128)(length + length - 1) };

yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (UInt128)i)), (UInt128)(length + length - 1) };
yield return new object[] { Shuffler.Shuffle(Enumerable.Range(length, length).Select(i => (UInt128)i).ToArray()), (UInt128)(length + length - 1) };
}
}
}
29 changes: 11 additions & 18 deletions tests/System.Linq.Tests/Stubs/TestData/SkipTakeData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,27 @@

// Original code: https://github.com/dotnet/runtime/blob/v9.0.3/src/libraries/Common/tests/System/Linq/SkipTakeData.cs

namespace System.Linq;
namespace System.Linq.Tests;

public class SkipTakeData
{
public static IEnumerable<object[]> EnumerableData()
public static TheoryData<int[], int> EnumerableData()
{
IEnumerable<int> sourceCounts = new[] { 0, 1, 2, 3, 5, 8, 13, 55, 100, 250 };
IEnumerable<int> sourceCounts = [0, 1, 2, 3, 5, 8, 13, 55, 100, 250];

IEnumerable<int> counts = new[] { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 100, 250, 500, int.MaxValue };
IEnumerable<int> counts = [1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 100, 250, 500, int.MaxValue];
counts = counts.Concat(counts.Select(c => -c)).Append(0).Append(int.MinValue);

return from sourceCount in sourceCounts
let source = Enumerable.Range(0, sourceCount)
from count in counts
select new object[] { source, count };
}
var items = from sourceCount in sourceCounts
let source = Enumerable.Range(0, sourceCount)
from count in counts
select new { source, count };

public static IEnumerable<object[]> EvaluationBehaviorData()
{
return Enumerable.Range(-1, 15).Select(count => new object[] { count });
return new(items.Select(x => (x.source.ToArray(), x.count)));
}

public static IEnumerable<object[]> QueryableData()
public static TheoryData<int> EvaluationBehaviorData()
{
return EnumerableData().Select(array =>
{
var enumerable = (IEnumerable<int>)array[0];
return new[] { enumerable.AsQueryable(), array[1] };
});
return new(Enumerable.Range(-1, 15).Select(count => count).ToArray());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ private static bool ComputeIsLinqSizeOptimized()
#endif
}
#else
public static bool IsLinqSpeedOptimized => IsSpeedOptimized;

public static bool IsSpeedOptimized => !IsSizeOptimized;
public static bool IsSizeOptimized => IsBrowser || IsWasi || IsAndroid || IsAppleMobile;
#endif
Expand Down
3 changes: 0 additions & 3 deletions tests/System.Linq.Tests/Stubs/xUnit/ConditionalUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,8 @@ public static bool IsEnable(Type type, string key)
case "IsDebuggerTypeProxyAttributeSupported" when PlatformDetection.IsDebuggerTypeProxyAttributeSupported:
case "IsNotBuiltWithAggressiveTrimming" when PlatformDetection.IsNotBuiltWithAggressiveTrimming:

#if NET10_0_OR_GREATER
case "IsLinqSpeedOptimized" when PlatformDetection.IsLinqSpeedOptimized:
#else
case "IsSpeedOptimized" when PlatformDetection.IsSpeedOptimized:
#endif
return true;
default:
return false;
Expand Down
Loading