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