|
5 | 5 | using System.Collections.Generic;
|
6 | 6 | using System.Collections.ObjectModel;
|
7 | 7 | using Xunit;
|
| 8 | +using Xunit.Sdk; |
8 | 9 |
|
9 | 10 | namespace System.Linq.Tests
|
10 | 11 | {
|
@@ -243,6 +244,7 @@ protected static IEnumerable<T> FlipIsCollection<T>(IEnumerable<T> source)
|
243 | 244 | {
|
244 | 245 | return source is ICollection<T> ? ForceNotCollection(source) : new List<T>(source);
|
245 | 246 | }
|
| 247 | + |
246 | 248 | protected static T[] Repeat<T>(Func<int, T> factory, int count)
|
247 | 249 | {
|
248 | 250 | T[] results = new T[count];
|
@@ -316,26 +318,83 @@ protected static IEnumerable<IEnumerable<T>> CreateSources<T>(IEnumerable<T> sou
|
316 | 318 | }
|
317 | 319 | }
|
318 | 320 |
|
319 |
| - protected static List<Func<IEnumerable<T>, IEnumerable<T>>> IdentityTransforms<T>() |
| 321 | + protected static IEnumerable<Func<IEnumerable<T>, IEnumerable<T>>> IdentityTransforms<T>() |
320 | 322 | {
|
321 |
| - // All of these transforms should take an enumerable and produce |
322 |
| - // another enumerable with the same contents. |
323 |
| - return new List<Func<IEnumerable<T>, IEnumerable<T>>> |
| 323 | + // Various collection types all representing the same source. |
| 324 | + List<Func<IEnumerable<T>, IEnumerable<T>>> sources = |
| 325 | + [ |
| 326 | + e => e, // original |
| 327 | + e => e.ToArray(), // T[] |
| 328 | + e => e.ToList(), // List<T> |
| 329 | + e => new ReadOnlyCollection<T>(e.ToArray()), // IList<T> that's not List<T>/T[] |
| 330 | + e => new TestCollection<T>(e.ToArray()), // ICollection<T> that's not IList<T> |
| 331 | + e => new TestReadOnlyCollection<T>(e.ToArray()), // IReadOnlyCollection<T> that's not ICollection<T> |
| 332 | + e => ForceNotCollection(e), // IEnumerable<T> with no other interfaces |
| 333 | + ]; |
| 334 | + if (typeof(T) == typeof(char)) |
324 | 335 | {
|
325 |
| - e => e, |
326 |
| - e => e.ToArray(), |
327 |
| - e => e.ToList(), |
328 |
| - e => e.ToList().Take(int.MaxValue), |
| 336 | + sources.Add(e => (IEnumerable<T>)(object)string.Concat((IEnumerable<char>)(object)e)); // string |
| 337 | + } |
| 338 | + |
| 339 | + // Various transforms that all yield the same elements as the source. |
| 340 | + List<Func<IEnumerable<T>, IEnumerable<T>>> transforms = |
| 341 | + [ |
| 342 | + // Append |
| 343 | + e => |
| 344 | + { |
| 345 | + T[] values = e.ToArray(); |
| 346 | + return values.Length == 0 ? [] : values[0..^1].Append(values[^1]); |
| 347 | + }, |
| 348 | + |
| 349 | + // Concat |
| 350 | + e => e.Concat(ForceNotCollection<T>([])), |
| 351 | + e => ForceNotCollection<T>([]).Concat(e), |
| 352 | + |
| 353 | + // Prepend |
| 354 | + e => |
| 355 | + { |
| 356 | + T[] values = e.ToArray(); |
| 357 | + return values.Length == 0 ? [] : values[1..].Prepend(values[0]); |
| 358 | + }, |
| 359 | + |
| 360 | + // Reverse |
| 361 | + e => e.Reverse().Reverse(), |
| 362 | + |
| 363 | + // Select |
329 | 364 | e => e.Select(i => i),
|
330 |
| - e => e.Select(i => i).Take(int.MaxValue), |
331 |
| - e => e.Select(i => i).Where(i => true), |
| 365 | + |
| 366 | + // SelectMany |
| 367 | + e => e.SelectMany<T, T>(i => [i]), |
| 368 | + |
| 369 | + // Take |
| 370 | + e => e.Take(int.MaxValue), |
| 371 | + e => e.TakeLast(int.MaxValue), |
| 372 | + e => e.TakeWhile(i => true), |
| 373 | + |
| 374 | + // Skip |
| 375 | + e => e.SkipWhile(i => false), |
| 376 | + |
| 377 | + // Where |
332 | 378 | e => e.Where(i => true),
|
333 |
| - e => e.Concat(Array.Empty<T>()), |
334 |
| - e => e.Concat(ForceNotCollection(Array.Empty<T>())), |
335 |
| - e => ForceNotCollection(e), |
336 |
| - e => ForceNotCollection(e).Skip(0), |
337 |
| - e => new ReadOnlyCollection<T>(e.ToArray()), |
338 |
| - }; |
| 379 | + ]; |
| 380 | + |
| 381 | + foreach (Func<IEnumerable<T>, IEnumerable<T>> source in sources) |
| 382 | + { |
| 383 | + // Yield the source itself. |
| 384 | + yield return source; |
| 385 | + |
| 386 | + foreach (Func<IEnumerable<T>, IEnumerable<T>> transform in transforms) |
| 387 | + { |
| 388 | + // Yield a single transform on the source |
| 389 | + yield return e => transform(source(e)); |
| 390 | + |
| 391 | + foreach (Func<IEnumerable<T>, IEnumerable<T>> transform2 in transforms) |
| 392 | + { |
| 393 | + // Yield a second transform on the first transform on the source. |
| 394 | + yield return e => transform2(transform(source(e))); |
| 395 | + } |
| 396 | + } |
| 397 | + } |
339 | 398 | }
|
340 | 399 |
|
341 | 400 | protected sealed class DelegateIterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>
|
|
0 commit comments