1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections.Generic;
7 using Xunit;
8 
9 namespace System.Linq.Tests
10 {
11     public class TakeTests : EnumerableTests
12     {
GuaranteeNotIList(IEnumerable<T> source)13         private static IEnumerable<T> GuaranteeNotIList<T>(IEnumerable<T> source)
14         {
15             foreach (T element in source)
16                 yield return element;
17         }
18 
19         [Fact]
SameResultsRepeatCallsIntQuery()20         public void SameResultsRepeatCallsIntQuery()
21         {
22             var q = from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 }
23                     where x > Int32.MinValue
24                     select x;
25 
26             Assert.Equal(q.Take(9), q.Take(9));
27         }
28 
29         [Fact]
SameResultsRepeatCallsIntQueryIList()30         public void SameResultsRepeatCallsIntQueryIList()
31         {
32             var q = (from x in new[] { 9999, 0, 888, -1, 66, -777, 1, 2, -12345 }
33                      where x > Int32.MinValue
34                      select x).ToList();
35 
36             Assert.Equal(q.Take(9), q.Take(9));
37         }
38 
39         [Fact]
SameResultsRepeatCallsStringQuery()40         public void SameResultsRepeatCallsStringQuery()
41         {
42             var q = from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty }
43                     where !String.IsNullOrEmpty(x)
44                     select x;
45 
46             Assert.Equal(q.Take(7), q.Take(7));
47         }
48 
49         [Fact]
SameResultsRepeatCallsStringQueryIList()50         public void SameResultsRepeatCallsStringQueryIList()
51         {
52             var q = (from x in new[] { "!@#$%^", "C", "AAA", "", "Calling Twice", "SoS", String.Empty }
53                      where !String.IsNullOrEmpty(x)
54                      select x).ToList();
55 
56             Assert.Equal(q.Take(7), q.Take(7));
57         }
58 
59         [Fact]
SourceEmptyCountPositive()60         public void SourceEmptyCountPositive()
61         {
62             int[] source = { };
63             Assert.Empty(source.Take(5));
64         }
65 
66         [Fact]
SourceEmptyCountPositiveNotIList()67         public void SourceEmptyCountPositiveNotIList()
68         {
69             var source = NumberRangeGuaranteedNotCollectionType(0, 0);
70             Assert.Empty(source.Take(5));
71         }
72 
73         [Fact]
SourceNonEmptyCountNegative()74         public void SourceNonEmptyCountNegative()
75         {
76             int[] source = { 2, 5, 9, 1 };
77             Assert.Empty(source.Take(-5));
78         }
79 
80         [Fact]
SourceNonEmptyCountNegativeNotIList()81         public void SourceNonEmptyCountNegativeNotIList()
82         {
83             var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 });
84             Assert.Empty(source.Take(-5));
85         }
86 
87         [Fact]
SourceNonEmptyCountZero()88         public void SourceNonEmptyCountZero()
89         {
90             int[] source = { 2, 5, 9, 1 };
91             Assert.Empty(source.Take(0));
92         }
93 
94         [Fact]
SourceNonEmptyCountZeroNotIList()95         public void SourceNonEmptyCountZeroNotIList()
96         {
97             var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 });
98             Assert.Empty(source.Take(0));
99         }
100 
101         [Fact]
SourceNonEmptyCountOne()102         public void SourceNonEmptyCountOne()
103         {
104             int[] source = { 2, 5, 9, 1 };
105             int[] expected = { 2 };
106 
107             Assert.Equal(expected, source.Take(1));
108         }
109 
110         [Fact]
SourceNonEmptyCountOneNotIList()111         public void SourceNonEmptyCountOneNotIList()
112         {
113             var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 });
114             int[] expected = { 2 };
115 
116             Assert.Equal(expected, source.Take(1));
117         }
118 
119         [Fact]
SourceNonEmptyTakeAllExactly()120         public void SourceNonEmptyTakeAllExactly()
121         {
122             int[] source = { 2, 5, 9, 1 };
123 
124             Assert.Equal(source, source.Take(source.Length));
125         }
126 
127         [Fact]
SourceNonEmptyTakeAllExactlyNotIList()128         public void SourceNonEmptyTakeAllExactlyNotIList()
129         {
130             var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 });
131 
132             Assert.Equal(source, source.Take(source.Count()));
133         }
134 
135         [Fact]
SourceNonEmptyTakeAllButOne()136         public void SourceNonEmptyTakeAllButOne()
137         {
138             int[] source = { 2, 5, 9, 1 };
139             int[] expected = { 2, 5, 9 };
140 
141             Assert.Equal(expected, source.Take(3));
142         }
143 
144         [Fact]
RunOnce()145         public void RunOnce()
146         {
147             int[] source = { 2, 5, 9, 1 };
148             int[] expected = { 2, 5, 9 };
149 
150             Assert.Equal(expected, source.RunOnce().Take(3));
151         }
152 
153         [Fact]
SourceNonEmptyTakeAllButOneNotIList()154         public void SourceNonEmptyTakeAllButOneNotIList()
155         {
156             var source = GuaranteeNotIList(new[] { 2, 5, 9, 1 });
157             int[] expected = { 2, 5, 9 };
158 
159             Assert.Equal(expected, source.Take(3));
160         }
161 
162         [Fact]
SourceNonEmptyTakeExcessive()163         public void SourceNonEmptyTakeExcessive()
164         {
165             int?[] source = { 2, 5, null, 9, 1 };
166 
167             Assert.Equal(source, source.Take(source.Length + 1));
168         }
169 
170         [Fact]
SourceNonEmptyTakeExcessiveNotIList()171         public void SourceNonEmptyTakeExcessiveNotIList()
172         {
173             var source = GuaranteeNotIList(new int?[] { 2, 5, null, 9, 1 });
174 
175             Assert.Equal(source, source.Take(source.Count() + 1));
176         }
177 
178         [Fact]
ThrowsOnNullSource()179         public void ThrowsOnNullSource()
180         {
181             int[] source = null;
182             AssertExtensions.Throws<ArgumentNullException>("source", () => source.Take(5));
183         }
184 
185         [Fact]
ForcedToEnumeratorDoesntEnumerate()186         public void ForcedToEnumeratorDoesntEnumerate()
187         {
188             var iterator = NumberRangeGuaranteedNotCollectionType(0, 3).Take(2);
189             // Don't insist on this behaviour, but check it's correct if it happens
190             var en = iterator as IEnumerator<int>;
191             Assert.False(en != null && en.MoveNext());
192         }
193 
194         [Fact]
Count()195         public void Count()
196         {
197             Assert.Equal(2, NumberRangeGuaranteedNotCollectionType(0, 3).Take(2).Count());
198             Assert.Equal(2, new[] { 1, 2, 3 }.Take(2).Count());
199             Assert.Equal(0, NumberRangeGuaranteedNotCollectionType(0, 3).Take(0).Count());
200         }
201 
202         [Fact]
ForcedToEnumeratorDoesntEnumerateIList()203         public void ForcedToEnumeratorDoesntEnumerateIList()
204         {
205             var iterator = NumberRangeGuaranteedNotCollectionType(0, 3).ToList().Take(2);
206             // Don't insist on this behaviour, but check it's correct if it happens
207             var en = iterator as IEnumerator<int>;
208             Assert.False(en != null && en.MoveNext());
209         }
210 
211         [Fact]
FollowWithTake()212         public void FollowWithTake()
213         {
214             var source = new[] { 5, 6, 7, 8 };
215             var expected = new[] { 5, 6 };
216             Assert.Equal(expected, source.Take(5).Take(3).Take(2).Take(40));
217         }
218 
219         [Fact]
FollowWithTakeNotIList()220         public void FollowWithTakeNotIList()
221         {
222             var source = NumberRangeGuaranteedNotCollectionType(5, 4);
223             var expected = new[] { 5, 6 };
224             Assert.Equal(expected, source.Take(5).Take(3).Take(2));
225         }
226 
227         [Fact]
FollowWithSkip()228         public void FollowWithSkip()
229         {
230             var source = new[] { 1, 2, 3, 4, 5, 6 };
231             var expected = new[] { 3, 4, 5 };
232             Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4));
233         }
234 
235         [Fact]
FollowWithSkipNotIList()236         public void FollowWithSkipNotIList()
237         {
238             var source = NumberRangeGuaranteedNotCollectionType(1, 6);
239             var expected = new[] { 3, 4, 5 };
240             Assert.Equal(expected, source.Take(5).Skip(2).Skip(-4));
241         }
242 
243         [Fact]
ElementAt()244         public void ElementAt()
245         {
246             var source = new[] { 1, 2, 3, 4, 5, 6 };
247             var taken = source.Take(3);
248             Assert.Equal(1, taken.ElementAt(0));
249             Assert.Equal(3, taken.ElementAt(2));
250             AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => taken.ElementAt(-1));
251             AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => taken.ElementAt(3));
252         }
253 
254         [Fact]
ElementAtNotIList()255         public void ElementAtNotIList()
256         {
257             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5, 6 });
258             var taken = source.Take(3);
259             Assert.Equal(1, taken.ElementAt(0));
260             Assert.Equal(3, taken.ElementAt(2));
261             AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => taken.ElementAt(-1));
262             AssertExtensions.Throws<ArgumentOutOfRangeException>("index", () => taken.ElementAt(3));
263         }
264 
265         [Fact]
ElementAtOrDefault()266         public void ElementAtOrDefault()
267         {
268             var source = new[] { 1, 2, 3, 4, 5, 6 };
269             var taken = source.Take(3);
270             Assert.Equal(1, taken.ElementAtOrDefault(0));
271             Assert.Equal(3, taken.ElementAtOrDefault(2));
272             Assert.Equal(0, taken.ElementAtOrDefault(-1));
273             Assert.Equal(0, taken.ElementAtOrDefault(3));
274         }
275 
276         [Fact]
ElementAtOrDefaultNotIList()277         public void ElementAtOrDefaultNotIList()
278         {
279             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5, 6 });
280             var taken = source.Take(3);
281             Assert.Equal(1, taken.ElementAtOrDefault(0));
282             Assert.Equal(3, taken.ElementAtOrDefault(2));
283             Assert.Equal(0, taken.ElementAtOrDefault(-1));
284             Assert.Equal(0, taken.ElementAtOrDefault(3));
285         }
286 
287         [Fact]
First()288         public void First()
289         {
290             var source = new[] { 1, 2, 3, 4, 5 };
291             Assert.Equal(1, source.Take(1).First());
292             Assert.Equal(1, source.Take(4).First());
293             Assert.Equal(1, source.Take(40).First());
294             Assert.Throws<InvalidOperationException>(() => source.Take(0).First());
295             Assert.Throws<InvalidOperationException>(() => source.Skip(5).Take(10).First());
296         }
297 
298         [Fact]
FirstNotIList()299         public void FirstNotIList()
300         {
301             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
302             Assert.Equal(1, source.Take(1).First());
303             Assert.Equal(1, source.Take(4).First());
304             Assert.Equal(1, source.Take(40).First());
305             Assert.Throws<InvalidOperationException>(() => source.Take(0).First());
306             Assert.Throws<InvalidOperationException>(() => source.Skip(5).Take(10).First());
307         }
308 
309         [Fact]
FirstOrDefault()310         public void FirstOrDefault()
311         {
312             var source = new[] { 1, 2, 3, 4, 5 };
313             Assert.Equal(1, source.Take(1).FirstOrDefault());
314             Assert.Equal(1, source.Take(4).FirstOrDefault());
315             Assert.Equal(1, source.Take(40).FirstOrDefault());
316             Assert.Equal(0, source.Take(0).FirstOrDefault());
317             Assert.Equal(0, source.Skip(5).Take(10).FirstOrDefault());
318         }
319 
320         [Fact]
FirstOrDefaultNotIList()321         public void FirstOrDefaultNotIList()
322         {
323             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
324             Assert.Equal(1, source.Take(1).FirstOrDefault());
325             Assert.Equal(1, source.Take(4).FirstOrDefault());
326             Assert.Equal(1, source.Take(40).FirstOrDefault());
327             Assert.Equal(0, source.Take(0).FirstOrDefault());
328             Assert.Equal(0, source.Skip(5).Take(10).FirstOrDefault());
329         }
330 
331         [Fact]
Last()332         public void Last()
333         {
334             var source = new[] { 1, 2, 3, 4, 5 };
335             Assert.Equal(1, source.Take(1).Last());
336             Assert.Equal(5, source.Take(5).Last());
337             Assert.Equal(5, source.Take(40).Last());
338             Assert.Throws<InvalidOperationException>(() => source.Take(0).Last());
339             Assert.Throws<InvalidOperationException>(() => Array.Empty<int>().Take(40).Last());
340         }
341 
342         [Fact]
LastNotIList()343         public void LastNotIList()
344         {
345             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
346             Assert.Equal(1, source.Take(1).Last());
347             Assert.Equal(5, source.Take(5).Last());
348             Assert.Equal(5, source.Take(40).Last());
349             Assert.Throws<InvalidOperationException>(() => source.Take(0).Last());
350             Assert.Throws<InvalidOperationException>(() => GuaranteeNotIList(Array.Empty<int>()).Take(40).Last());
351         }
352 
353         [Fact]
LastOrDefault()354         public void LastOrDefault()
355         {
356             var source = new[] { 1, 2, 3, 4, 5 };
357             Assert.Equal(1, source.Take(1).LastOrDefault());
358             Assert.Equal(5, source.Take(5).LastOrDefault());
359             Assert.Equal(5, source.Take(40).LastOrDefault());
360             Assert.Equal(0, source.Take(0).LastOrDefault());
361             Assert.Equal(0, Array.Empty<int>().Take(40).LastOrDefault());
362         }
363 
364         [Fact]
LastOrDefaultNotIList()365         public void LastOrDefaultNotIList()
366         {
367             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
368             Assert.Equal(1, source.Take(1).LastOrDefault());
369             Assert.Equal(5, source.Take(5).LastOrDefault());
370             Assert.Equal(5, source.Take(40).LastOrDefault());
371             Assert.Equal(0, source.Take(0).LastOrDefault());
372             Assert.Equal(0, GuaranteeNotIList(Array.Empty<int>()).Take(40).LastOrDefault());
373         }
374 
375         [Fact]
ToArray()376         public void ToArray()
377         {
378             var source = new[] { 1, 2, 3, 4, 5 };
379             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(5).ToArray());
380             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(6).ToArray());
381             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(40).ToArray());
382             Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).ToArray());
383             Assert.Equal(1, source.Take(1).ToArray().Single());
384             Assert.Empty(source.Take(0).ToArray());
385             Assert.Empty(source.Take(-10).ToArray());
386         }
387 
388         [Fact]
ToArrayNotList()389         public void ToArrayNotList()
390         {
391             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
392             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(5).ToArray());
393             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(6).ToArray());
394             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(40).ToArray());
395             Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).ToArray());
396             Assert.Equal(1, source.Take(1).ToArray().Single());
397             Assert.Empty(source.Take(0).ToArray());
398             Assert.Empty(source.Take(-10).ToArray());
399         }
400 
401         [Fact]
ToList()402         public void ToList()
403         {
404             var source = new[] { 1, 2, 3, 4, 5 };
405             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(5).ToList());
406             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(6).ToList());
407             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(40).ToList());
408             Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).ToList());
409             Assert.Equal(1, source.Take(1).ToList().Single());
410             Assert.Empty(source.Take(0).ToList());
411             Assert.Empty(source.Take(-10).ToList());
412         }
413 
414         [Fact]
ToListNotList()415         public void ToListNotList()
416         {
417             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
418             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(5).ToList());
419             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(6).ToList());
420             Assert.Equal(new[] { 1, 2, 3, 4, 5 }, source.Take(40).ToList());
421             Assert.Equal(new[] { 1, 2, 3, 4 }, source.Take(4).ToList());
422             Assert.Equal(1, source.Take(1).ToList().Single());
423             Assert.Empty(source.Take(0).ToList());
424             Assert.Empty(source.Take(-10).ToList());
425         }
426 
427         [Fact]
TakeCanOnlyBeOneList()428         public void TakeCanOnlyBeOneList()
429         {
430             var source = new[] { 2, 4, 6, 8, 10 };
431             Assert.Equal(new[] { 2 }, source.Take(1));
432             Assert.Equal(new[] { 4 }, source.Skip(1).Take(1));
433             Assert.Equal(new[] { 6 }, source.Take(3).Skip(2));
434             Assert.Equal(new[] { 2 }, source.Take(3).Take(1));
435         }
436 
437         [Fact]
TakeCanOnlyBeOneNotList()438         public void TakeCanOnlyBeOneNotList()
439         {
440             var source = GuaranteeNotIList(new[] { 2, 4, 6, 8, 10 });
441             Assert.Equal(new[] { 2 }, source.Take(1));
442             Assert.Equal(new[] { 4 }, source.Skip(1).Take(1));
443             Assert.Equal(new[] { 6 }, source.Take(3).Skip(2));
444             Assert.Equal(new[] { 2 }, source.Take(3).Take(1));
445         }
446 
447         [Fact]
RepeatEnumerating()448         public void RepeatEnumerating()
449         {
450             var source = new[] { 1, 2, 3, 4, 5 };
451             var taken = source.Take(3);
452             Assert.Equal(taken, taken);
453         }
454 
455         [Fact]
RepeatEnumeratingNotList()456         public void RepeatEnumeratingNotList()
457         {
458             var source = GuaranteeNotIList(new[] { 1, 2, 3, 4, 5 });
459             var taken = source.Take(3);
460             Assert.Equal(taken, taken);
461         }
462 
463         [Theory]
464         [InlineData(1000)]
465         [InlineData(1000000)]
466         [InlineData(int.MaxValue)]
467         [SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, ".NET Core optimizes Take(...).Skip(...) on lazy sequences to avoid unecessary allocation. Without this optimization this test takes many minutes. See https://github.com/dotnet/corefx/pull/13628.")]
LazySkipAllTakenForLargeNumbers(int largeNumber)468         public void LazySkipAllTakenForLargeNumbers(int largeNumber)
469         {
470             Assert.Empty(new FastInfiniteEnumerator<int>().Take(largeNumber).Skip(largeNumber));
471             Assert.Empty(new FastInfiniteEnumerator<int>().Take(largeNumber).Skip(largeNumber).Skip(42));
472             Assert.Empty(new FastInfiniteEnumerator<int>().Take(largeNumber).Skip(largeNumber / 2).Skip(largeNumber / 2 + 1));
473         }
474 
475         [Fact]
LazyOverflowRegression()476         public void LazyOverflowRegression()
477         {
478             var range = NumberRangeGuaranteedNotCollectionType(1, 100);
479             var skipped = range.Skip(42); // Min index is 42.
480             var taken = skipped.Take(int.MaxValue); // May try to calculate max index as 42 + int.MaxValue, leading to integer overflow.
481             Assert.Equal(Enumerable.Range(43, 100 - 42), taken);
482             Assert.Equal(100 - 42, taken.Count());
483             Assert.Equal(Enumerable.Range(43, 100 - 42), taken.ToArray());
484             Assert.Equal(Enumerable.Range(43, 100 - 42), taken.ToList());
485         }
486 
487         [Theory]
488         [InlineData(0, 0, 0)]
489         [InlineData(1, 1, 1)]
490         [InlineData(0, int.MaxValue, 100)]
491         [InlineData(int.MaxValue, 0, 0)]
492         [InlineData(0xffff, 1, 0)]
493         [InlineData(1, 0xffff, 99)]
494         [InlineData(int.MaxValue, int.MaxValue, 0)]
495         [InlineData(1, int.MaxValue, 99)] // Regression test: The max index is precisely int.MaxValue.
496         [InlineData(0, 100, 100)]
497         [InlineData(10, 100, 90)]
CountOfLazySkipTakeChain(int skip, int take, int expected)498         public void CountOfLazySkipTakeChain(int skip, int take, int expected)
499         {
500             var partition = NumberRangeGuaranteedNotCollectionType(1, 100).Skip(skip).Take(take);
501             Assert.Equal(expected, partition.Count());
502             Assert.Equal(expected, partition.Select(i => i).Count());
503             Assert.Equal(expected, partition.Select(i => i).ToArray().Length);
504         }
505 
506         [Theory]
507         [InlineData(new[] { 1, 2, 3, 4 }, 1, 3, 2, 4)]
508         [InlineData(new[] { 1 }, 0, 1, 1, 1)]
509         [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 1, int.MaxValue, 2, 13)] // Regression test: The max index is precisely int.MaxValue.
510         [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 0, 2, 1, 2)]
511         [InlineData(new[] { 1, 2, 3, 5, 8, 13 }, 500, 2, 0, 0)]
512         [InlineData(new int[] { }, 10, 8, 0, 0)]
FirstAndLastOfLazySkipTakeChain(IEnumerable<int> source, int skip, int take, int first, int last)513         public void FirstAndLastOfLazySkipTakeChain(IEnumerable<int> source, int skip, int take, int first, int last)
514         {
515             var partition = ForceNotCollection(source).Skip(skip).Take(take);
516 
517             Assert.Equal(first, partition.FirstOrDefault());
518             Assert.Equal(first, partition.ElementAtOrDefault(0));
519             Assert.Equal(last, partition.LastOrDefault());
520             Assert.Equal(last, partition.ElementAtOrDefault(partition.Count() - 1));
521         }
522 
523         [Theory]
524         [InlineData(new[] { 1, 2, 3, 4, 5 }, 1, 3, new[] { -1, 0, 1, 2 }, new[] { 0, 2, 3, 4 })]
525         [InlineData(new[] { 0xfefe, 7000, 123 }, 0, 3, new[] { -1, 0, 1, 2 }, new[] { 0, 0xfefe, 7000, 123 })]
526         [InlineData(new[] { 0xfefe }, 100, 100, new[] { -1, 0, 1, 2 }, new[] { 0, 0, 0, 0 })]
527         [InlineData(new[] { 0xfefe, 123, 456, 7890, 5555, 55 }, 1, 10, new[] { -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }, new[] { 0, 123, 456, 7890, 5555, 55, 0, 0, 0, 0, 0, 0, 0 })]
ElementAtOfLazySkipTakeChain(IEnumerable<int> source, int skip, int take, int[] indices, int[] expectedValues)528         public void ElementAtOfLazySkipTakeChain(IEnumerable<int> source, int skip, int take, int[] indices, int[] expectedValues)
529         {
530             var partition = ForceNotCollection(source).Skip(skip).Take(take);
531 
532             Assert.Equal(indices.Length, expectedValues.Length);
533             for (int i = 0; i < indices.Length; i++)
534             {
535                 Assert.Equal(expectedValues[i], partition.ElementAtOrDefault(indices[i]));
536             }
537         }
538 
539         [Theory]
540         [InlineData(0, -1)]
541         [InlineData(0, 0)]
542         [InlineData(1, 0)]
543         [InlineData(2, 1)]
544         [InlineData(2, 2)]
545         [InlineData(2, 3)]
DisposeSource(int sourceCount, int count)546         public void DisposeSource(int sourceCount, int count)
547         {
548             int state = 0;
549 
550             var source = new DelegateIterator<int>(
551                 moveNext: () => ++state <= sourceCount,
552                 current: () => 0,
553                 dispose: () => state = -1);
554 
555             IEnumerator<int> iterator = source.Take(count).GetEnumerator();
556             int iteratorCount = Math.Min(sourceCount, Math.Max(0, count));
557             Assert.All(Enumerable.Range(0, iteratorCount), _ => Assert.True(iterator.MoveNext()));
558 
559             Assert.False(iterator.MoveNext());
560 
561             // Unlike Skip, Take can tell straightaway that it can return a sequence with no elements if count <= 0.
562             // The enumerable it returns is a specialized empty iterator that has no connections to the source. Hence,
563             // after MoveNext returns false under those circumstances, it won't invoke Dispose on our enumerator.
564             int expected = count <= 0 ? 0 : -1;
565             Assert.Equal(expected, state);
566         }
567     }
568 }
569