[arm64] Fix finally abort
[mono.git] / mcs / class / System.Core / Test / System.Linq / EnumerableFixture.cs
1 #region License, Terms and Author(s)
2 //
3 // BackLINQ
4 // Copyright (c) 2008 Atif Aziz. All rights reserved.
5 //
6 //  Author(s):
7 //
8 //      Dominik Hug, http://www.dominikhug.ch
9 //
10 // This library is free software; you can redistribute it and/or modify it
11 // under the terms of the New BSD License, a copy of which should have
12 // been delivered along with this distribution.
13 //
14 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
17 // PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 //
26 #endregion
27
28 using System;
29 using System.Collections;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.Globalization;
33 using System.Text;
34 using System.Threading;
35 using NUnit.Framework;
36 using System.Linq;
37 using NUnit.Framework.Constraints;
38 using System.Diagnostics;
39
40 namespace MonoTests.System.Linq
41 {
42         [TestFixture]
43         public sealed class EnumerableFixture {
44                 private CultureInfo initialCulture; // Thread culture saved during Setup to be undone in TearDown.
45                 private AssertionHandler tearDownAssertions;
46
47                 private delegate void AssertionHandler ();
48
49                 [SetUp]
50                 public void SetUp ()
51                 {
52                         tearDownAssertions = null;
53                         initialCulture = Thread.CurrentThread.CurrentCulture;
54                         Thread.CurrentThread.CurrentCulture = new CultureInfo ("de-CH");
55                 }
56
57                 [TearDown]
58                 public void TearDown ()
59                 {
60                         if (tearDownAssertions != null)
61                                 tearDownAssertions ();
62                         Thread.CurrentThread.CurrentCulture = initialCulture;
63                 }
64
65                 [Test]
66                 [ExpectedException (typeof (InvalidOperationException))]
67                 public void Aggregate_EmptySource_ThrowsInvalidOperationException ()
68                 {
69                         var source = Read<object> ();
70                         source.Aggregate (delegate { throw new NotImplementedException (); });
71                 }
72
73                 [Test]
74                 public void Aggregate_AddFuncOnIntegers_ReturnsTotal ()
75                 {
76                         var source = Read (12, 34, 56, 78, 910, 1112, 1314, 1516, 1718, 1920);
77                         var result = source.Aggregate ((a, b) => a + b);
78                         Assert.That (result, Is.EqualTo (8670));
79                 }
80
81                 [Test]
82                 public void Aggregate_AddFuncOnIntegersWithSeed_ReturnsTotal ()
83                 {
84                         var source = Read (12, 34, 56, 78, 910, 1112, 1314, 1516, 1718, 1920);
85                         var result = source.Aggregate (100, (a, b) => a + b);
86                         Assert.That (result, Is.EqualTo (8770));
87                 }
88
89                 [Test]
90                 [ExpectedException (typeof (ArgumentNullException))]
91                 public void Aggregate_NullSource_ThrowsArgumentNullException ()
92                 {
93                         Enumerable.Aggregate<object> (null, delegate { throw new NotImplementedException (); });
94                 }
95
96                 [Test]
97                 [ExpectedException (typeof (ArgumentNullException))]
98                 public void Aggregate_NullFunc_ThrowsArgumentNullException ()
99                 {
100                         Read<object> ().Aggregate (null);
101                 }
102
103                 [Test]
104                 public void Empty_YieldsEmptySource ()
105                 {
106                         var source = Enumerable.Empty<string> ();
107                         Assert.That (source, Is.Not.Null);
108                         var e = source.GetEnumerator ();
109                         Assert.That (e, Is.Not.Null);
110                         Assert.That (e.MoveNext (), Is.False);
111                 }
112
113                 [Test]
114                 [ExpectedException (typeof (ArgumentNullException))]
115                 public void Cast_NullSource_ThrowsArgumentNullException ()
116                 {
117                         Enumerable.Cast<object> (null);
118                 }
119
120                 [Test]
121                 [ExpectedException (typeof (InvalidCastException))]
122                 public void Cast_InvalidSource_ThrowsInvalidCastException ()
123                 {
124                         var source = Read (1000, "hello", new object ());
125                         var e = source.Cast<byte> ().GetEnumerator ();
126                         e.MoveNext (); // Do something so Cast will really run (deferred execution)
127                 }
128
129                 [Test]
130                 public void Cast_ObjectSourceContainingIntegers_YieldsDowncastedIntegers ()
131                 {
132                         var source = Read<object> (1, 10, 100);
133                         source.Cast<int> ().AssertEquals (1, 10, 100);
134                 }
135
136                 [Test]
137                 public void Cast_Integers_YieldsUpcastedObjects ()
138                 {
139 #if false
140                         // shouldn't this be inferred?
141                         Read (1, 10, 100).Cast<object> ().AssertEquals (1, 10, 100);
142 #else
143                         Read (1, 10, 100).Cast<object> ().AssertEquals<object> (1, 10, 100);
144 #endif
145                 }
146
147                 [Test]
148                 [ExpectedException (typeof (ArgumentNullException))]
149                 public void All_NullSource_ThrowsArgumentNullException ()
150                 {
151                         Enumerable.All (null, (int i) => { throw new NotImplementedException (); });
152                 }
153
154                 [Test]
155                 public void All_SomeSourceElementsNotSatifyingPredicate_ReturnsFalse ()
156                 {
157                         var source = Read (-100, -1, 0, 1, 100);
158                         Assert.That (source.All (i => i < 0), Is.False);
159                 }
160
161                 [Test]
162                 public void All_SourceElementsSatisfyingPredicate_ReturnsTrue ()
163                 {
164                         var source = Read (-100, -1, 0, 1, 100);
165                         Assert.That (source.All (i => i >= -100), Is.True);
166                 }
167
168                 [Test]
169                 [ExpectedException (typeof (ArgumentNullException))]
170                 public void Any_NullSource_ThrowsArgumentNullException ()
171                 {
172                         Enumerable.Any<object> (null);
173                 }
174
175                 [Test]
176                 public void Any_EmptySource_ReturnsFalse ()
177                 {
178                         var source = Read<object> ();
179                         Assert.That (source.Any (), Is.False);
180                 }
181
182                 [Test]
183                 public void Any_NonEmptySource_ReturnsTrue ()
184                 {
185                         var source = Read (new object ());
186                         Assert.That (source.Any (), Is.True);
187                 }
188
189                 [Test]
190                 public void Any_PredicateArg_EmptySource_ReturnsFalse ()
191                 {
192                         var source = Read (new int [0]);
193                         Assert.That (source.Any (delegate { throw new NotImplementedException (); }), Is.False);
194                 }
195
196                 [Test]
197                 public void Any_PredicateArg_NonEmptySource_ReturnsTrue ()
198                 {
199                         Assert.That (Read (1, 2, 3, 4, 5).Any (i => i > 2), Is.True);
200                 }
201
202                 [Test]
203                 [ExpectedException (typeof (InvalidOperationException))]
204                 public void Average_EmptyLongSource_ThrowsInvalidOperationException ()
205                 {
206                         Read<long> ().Average ();
207                 }
208
209                 [Test]
210                 public void Average_Longs_ReturnsAverage ()
211                 {
212                         Assert.That (Read (25L, 75L).Average (), Is.EqualTo (50));
213                 }
214
215                 [Test]
216                 public void Average_SelectorArg_Longs_ReturnsAverage ()
217                 {
218                         Assert.That (Read (25L, 75L).Average (n => n * 2L), Is.EqualTo (100));
219                 }
220
221                 [Test]
222                 public void Average_EmptyNullableLongSource_Null ()
223                 {
224                         Assert.That (Read<long?> ().Average (), Is.Null);
225                 }
226
227                 [Test]
228                 public void Average_NullableLongsWithSomeNull_ReturnsAverage ()
229                 {
230                         Assert.That (Read<long?> (12L, null, 34L, null, 56L).Average (), Is.EqualTo (34.0));
231                 }
232
233                 [Test]
234                 public void Average_SelectorArg_NullableLongsWithSomeNull_ReturnsAverage ()
235                 {
236                         Assert.That (Read<long?> (12L, null, 34L, null, 56L).Average (n => n * 2L), Is.EqualTo (68.0));
237                 }
238
239                 [Test]
240                 public void Average_EmptyNullableIntegerSource_Null ()
241                 {
242                         Assert.That (Read<int?> ().Average (), Is.Null);
243                 }
244
245                 [Test]
246                 public void Average_NullableIntegersWithSomeNull_ReturnsAverage ()
247                 {
248                         Assert.That (Read<int?> (12, null, 34, null, 56).Average (), Is.EqualTo (34.0));
249                 }
250
251                 [Test]
252                 public void Average_SelectorArg_NullableIntegersWithSomeNull_ReturnsAverage ()
253                 {
254                         Assert.That (Read<int?> (12, null, 34, null, 56).Average (n => n * 2), Is.EqualTo (68.0));
255                 }
256
257                 [Test]
258                 [ExpectedException (typeof (InvalidOperationException))]
259                 public void Average_EmptyDecimalSource_ThrowsInvalidOperationException ()
260                 {
261                         Read<decimal> ().Average ();
262                 }
263
264                 [Test]
265                 public void Average_Decimals_ReturnsAverage ()
266                 {
267                         var source = Read (-10000m, 2.0001m, 50m);
268                         Assert.That (source.Average (), Is.EqualTo (-3315.999966).Within (0.00001));
269                 }
270
271                 [Test]
272                 public void Average_SelectorArg_Decimals_ReturnsAverage ()
273                 {
274                         var source = Read (-10000m, 2.0001m, 50m);
275                         Assert.That (source.Average (n => n * 2m), Is.EqualTo (-6631.999933).Within (0.00001));
276                 }
277
278                 [Test]
279                 [ExpectedException (typeof (InvalidOperationException))]
280                 public void Average_EmptySource_ThrowsInvalidOperationException ()
281                 {
282                         Read<int> ().Average ();
283                 }
284
285                 [Test]
286                 public void Average_EmptyNullableIntegerSource_ReturnsNull ()
287                 {
288                         Assert.That (Read<int?> ().Average (), Is.Null);
289                 }
290
291                 [Test]
292                 public void Average_SelectorArg_Integers_ReturnsAverage ()
293                 {
294                         Assert.That (Read (21, 22, 23, 24).Average (n => n * 2).Equals (45));
295                 }
296
297                 [Test]
298                 [ExpectedException (typeof (InvalidOperationException))]
299                 public void Average_EmptyDoubleSource_ThrowsInvalidOperationException ()
300                 {
301                         Read<double> ().Average ();
302                 }
303
304                 [Test]
305                 public void Average_Doubles_ReturnsAverage ()
306                 {
307                         var source = Read (-3.45, 9.001, 10000.01);
308                         Assert.That (source.Average (), Is.EqualTo (3335.187).Within (0.01));
309                 }
310
311                 [Test]
312                 public void Average_SelectorArg_Doubles_ReturnsAverage ()
313                 {
314                         var source = Read (-3.45, 9.001, 10000.01);
315                         Assert.That (source.Average (n => n * 2.0), Is.EqualTo (6670.374).Within (0.01));
316                 }
317
318                 [Test]
319                 [ExpectedException (typeof (InvalidOperationException))]
320                 public void Average_EmptyFloatSource_ThrowsInvalidOperationException ()
321                 {
322                         Read<float> ().Average ();
323                 }
324
325                 [Test]
326                 public void Average_Floats_ReturnsAverage ()
327                 {
328                         var source = Read (-3.45F, 9.001F, 10000.01F);
329                         Assert.That (source.Average (), Is.EqualTo (3335.187).Within (0.01));
330                 }
331
332                 [Test]
333                 public void Average_SelectorArg_Floats_ReturnsAverage ()
334                 {
335                         var source = Read (-3.45F, 9.001F, 10000.01F);
336                         Assert.That (source.Average (n => n * 2F), Is.EqualTo (6670.37354).Within (0.01));
337                 }
338
339                 [Test]
340                 public void Average_EmptyNullableFloatSource_Null ()
341                 {
342                         Assert.That (Read<float?> ().Average (), Is.Null);
343                 }
344
345                 [Test]
346                 public void Average_NullableFloatsWithSomeNulls_ReturnsAverage ()
347                 {
348                         var source = Read<float?> (-3.45F, null, 9.001F, null, 10000.01F);
349                         Assert.That (source.Average (), Is.EqualTo (3335.187).Within (0.01));
350                 }
351
352                 [Test]
353                 public void Average_SelectorArg_NullableFloatsWithSomeNulls_ReturnsAverage ()
354                 {
355                         var source = Read<float?> (-3.45F, null, 9.001F, null, 10000.01F);
356                         Assert.That (source.Average (n => n * 2F), Is.EqualTo (6670.37354).Within (0.01));
357                 }
358
359                 [Test]
360                 public void Average_EmptyNullableDoubleSource_Null ()
361                 {
362                         Assert.That (Read<double?> ().Average (), Is.Null);
363                 }
364
365                 [Test]
366                 public void Average_NullableDoublesWithSomeNulls_ReturnsAverage ()
367                 {
368                         var source = Read<double?> (-3.45, null, 9.001, null, 10000.01);
369                         Assert.That (source.Average (), Is.EqualTo (3335.187).Within (0.01));
370                 }
371
372                 [Test]
373                 public void Average_SelectorArg_NullableDoublesWithSomeNulls_ReturnsAverage ()
374                 {
375                         var source = Read<double?> (-3.45, null, 9.001, null, 10000.01);
376                         Assert.That (source.Average (n => n * 2.0), Is.EqualTo (6670.374).Within (0.01));
377                 }
378
379                 [Test]
380                 public void Average_EmptyNullableDecimalSource_Null ()
381                 {
382                         Assert.That (Read<decimal?> ().Average (), Is.Null);
383                 }
384
385                 [Test]
386                 public void Average_NullableDecimalsWithSomeNulls_ReturnsAverage ()
387                 {
388                         var source = Read<decimal?> (-3.45m, null, 9.001m, null, 10000.01m);
389                         Assert.That (source.Average (), Is.EqualTo (3335.187).Within (0.01));
390                 }
391
392                 [Test]
393                 public void Average_SelectorArg_NullableDecimalsWithSomeNulls_ReturnsAverage ()
394                 {
395                         var source = Read<decimal?> (-3.45m, null, 9.001m, null, 10000.01m);
396                         Assert.That (source.Average (n => n * 2m), Is.EqualTo (6670.374m).Within (0.01));
397                 }
398
399                 [Test]
400                 [ExpectedException (typeof (ArgumentNullException))]
401                 public void Concat_FirstSourceNull_ThrowsArgumentNullException ()
402                 {
403                         Enumerable.Concat (null, new object [0]);
404                 }
405
406                 [Test]
407                 [ExpectedException (typeof (ArgumentNullException))]
408                 public void Concat_SecondSourceNull_ThrowsArgumentNullException ()
409                 {
410                         new object [0].Concat (null);
411                 }
412
413                 [Test]
414                 public void Concat_TwoSequences_CombinedSequenceWhereElementsOfSecondFollowFirst ()
415                 {
416                         var first = Read (12, 34, 56);
417                         var second = Read (78, 910, 1112);
418                         first.Concat (second).AssertEquals (12, 34, 56, 78, 910, 1112);
419                 }
420
421                 [Test]
422                 public void Contains_SequenceContainingSoughtValue_ReturnsTrue ()
423                 {
424                         var source = Read (12, -15, 21);
425                         Assert.That (source.Contains (21), Is.True);
426                 }
427
428                 [Test]
429                 public void Contains_SequenceWithoutSoughtValue_ReturnsFalse ()
430                 {
431                         var source = Read (-2, 4, 8);
432                         Assert.That (source.Contains (9), Is.False);
433                 }
434
435                 [Test]
436                 public void Contains_CollectionOptimization_ReturnsTrueWithoutEnumerating ()
437                 {
438                         var source = new NonEnumerableList<int> (new [] { 1, 2, 3 });
439
440                         // IMPORTANT! Use the non-extension invocation style below
441                         //            to avoid calling List<T>.Contains instead of
442                         //            Enumerable.Contains.
443
444                         Assert.That (Enumerable.Contains (source, 3), Is.True);
445                 }
446
447                 [Test]
448                 public void Count_Integers_ReturnsNumberOfElements ()
449                 {
450                         Assert.That (Read (12, 34, 56).Count (), Is.EqualTo (3));
451                 }
452
453                 [Test]
454                 public void Count_PredicateArg_Strings_CountsOnlyStringsWithEvenLength ()
455                 {
456                         var source = Read ("A", "AB", "ABC", "ABCD");
457                         Assert.That (source.Count (s => s.Length % 2 == 0), Is.EqualTo (2));
458                 }
459
460                 [Test]
461                 public void DefaultIfEmpty_Integers_YieldsIntegersInOrder ()
462                 {
463                         var source = Read (12, 34, 56);
464                         source.DefaultIfEmpty (1).AssertEquals (12, 34, 56);
465                 }
466
467                 [Test]
468                 public void DefaultIfEmpty_EmptyIntegerSequence_ReturnsZero ()
469                 {
470                         var source = Read (new int [0]);
471                         source.DefaultIfEmpty ().AssertEquals (0);
472                 }
473
474                 [Test]
475                 public void DefaultIfEmpty_DefaultValueArg_EmptyIntegerSequenceAndNonZeroDefault_ReturnNonZeroDefault ()
476                 {
477                         var source = Read (new int [0]);
478                         source.DefaultIfEmpty (5).AssertEquals (5);
479                 }
480
481                 [Test]
482                 public void DefaultIfEmpty_DefaultValueArg_Integers_YieldsIntegersInOrder ()
483                 {
484                         var source = Read (12, 34, 56);
485                         source.DefaultIfEmpty (5).AssertEquals (12, 34, 56);
486                 }
487
488                 [Test]
489                 [ExpectedException (typeof (ArgumentNullException))]
490                 public void Distinct_NullSource_ThrowsArgumentNullException ()
491                 {
492                         Enumerable.Distinct<object> (null);
493                 }
494
495                 [Test]
496                 public void Distinct_IntegersWithSomeDuplicates_YieldsIntegersInSourceOrderWithoutDuplicates ()
497                 {
498                         var source = Read (12, 34, 34, 56, 78, 78, 78, 910, 78);
499                         source.Distinct ().AssertEquals (12, 34, 56, 78, 910);
500                 }
501
502                 [Test]
503                 public void Distinct_MixedCaseStringsWithCaseIgnoringComparer_YieldsFirstCaseOfEachDistinctStringInSourceOrder ()
504                 {
505                         var source = Read ("Foo Bar BAZ BaR baz FOo".Split ());
506                         source.Distinct (StringComparer.InvariantCultureIgnoreCase).AssertEquals ("Foo", "Bar", "BAZ");
507                 }
508
509                 [Test]
510                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
511                 public void ElementAt_IndexOutOfRange_ThrowsArgumentOutOfRangeException ()
512                 {
513                         var source = Read (3, 5, 7);
514                         source.ElementAt (3);
515                 }
516
517                 [Test]
518                 public void ElementAt_Integers_ReturnsValueAtGivenIndex ()
519                 {
520                         var source = new [] { 15, 2, 7 };
521                         Assert.That (Read (source).ElementAt (0), Is.EqualTo (15));
522                         Assert.That (Read (source).ElementAt (1), Is.EqualTo (2));
523                         Assert.That (Read (source).ElementAt (2), Is.EqualTo (7));
524                 }
525
526                 [Test]
527                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
528                 public void ElementAt_NegativeIndex_ThrowsArgumentOutOfRangeException ()
529                 {
530                         Read<int> ().ElementAt (-1);
531                 }
532
533                 [Test]
534                 public void ElementAt_ListOptimization_ReturnsValueAtGivenIndex ()
535                 {
536                         var source = new NonEnumerableList<int> (new [] { 1, 2, 3, 4, 5, 6 });
537                         Assert.That (source.ElementAt (2), Is.EqualTo (3));
538                 }
539
540                 [Test]
541                 public void ElementAt_ReadOnlyListOptimization_ReturnsValueAtGivenIndex()
542                 {
543                         var source = new NonEnumerableReadOnlyList<int> (new List<int> (new[] { 1, 2, 3, 4, 5, 6 }));
544                         Assert.That(source.ElementAt (2), Is.EqualTo (3));
545                 }
546
547                 [Test]
548                 public void ElementAtOrDefault_IntegersWithOutOfRangeIndex_ReturnsDefault ()
549                 {
550                         var source = Read (3, 6, 8);
551                         Assert.That (source.ElementAtOrDefault (3), Is.EqualTo (0));
552                 }
553
554                 [Test]
555                 public void ElementAtOrDefault_Integers_ReturnsValueAtGivenIndex ()
556                 {
557                         var source = Read (3, 6, 9);
558                         Assert.That (source.ElementAtOrDefault (2), Is.EqualTo (9));
559                 }
560
561                 [Test]
562                 public void ElementAtOrDefault_ListOptimization_ReturnsValueAtGivenIndex ()
563                 {
564                         var source = new NonEnumerableList<int> (new [] { 1, 2, 3, 4, 5, 6 });
565                         Assert.That (source.ElementAtOrDefault (2), Is.EqualTo (3));
566                 }
567
568                 [Test]
569                 public void ElementAtOrDefault_ReadOnlyListOptimization_ReturnsValueAtGivenIndex()
570                 {
571                         var source = new NonEnumerableReadOnlyList<int>(new List<int> (new[] { 1, 2, 3, 4, 5, 6 }));
572                         Assert.That(source.ElementAtOrDefault (2), Is.EqualTo (3));
573                 }
574
575                 [Test]
576                 public void ElementAtOrDefault_BooleansAndNegativeIndex_ReturnsDefault ()
577                 {
578                         var source = Read (true, false, true, false);
579                         Assert.That (source.ElementAtOrDefault (-3), Is.False);
580                 }
581
582                 [Test]
583                 public void ElementAtOrDefault_ObjectsWithOutOfRangeIndex_ReturnsNull ()
584                 {
585                         var source = Read (new object (), new object ());
586                         Assert.That (source.ElementAtOrDefault (2), Is.EqualTo (null));
587                 }
588
589                 [Test]
590                 public void ElementAtOrDefault_Objects_ReturnsValueAtGivenIndex ()
591                 {
592                         var second = new object ();
593                         var source = Read (new object (), second, new object ());
594                         Assert.That (source.ElementAt (1), Is.EqualTo (second));
595                 }
596
597                 [Test]
598                 [ExpectedException (typeof (ArgumentNullException))]
599                 public void Except_SecondArg_ArgumentNull_ThrowsArgumentNullException ()
600                 {
601                         Read<object> ().Except (null);
602                 }
603
604                 [Test]
605                 public void Except_SecondArg_ValidArgument_ReturnsDifference ()
606                 {
607                         var first = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
608                         var second = Read (1, 3, 5, 7, 9);
609                         first.Except (second).AssertEquals (2, 4, 6, 8, 10);
610                 }
611
612                 [Test]
613                 public void Except_SecondArgComparerArg_ComparerIsUsed ()
614                 {
615                         var first = Read ("albert", "john", "simon");
616                         var second = Read ("ALBERT");
617                         first.Except (second, StringComparer.CurrentCultureIgnoreCase).AssertEquals ("john", "simon");
618                 }
619
620                 [Test]
621                 [ExpectedException (typeof (InvalidOperationException))]
622                 public void First_EmptySource_ThrowsInvalidOperationException ()
623                 {
624                         Read<int> ().First ();
625                 }
626
627                 [Test]
628                 public void First_Integers_ReturnsFirst ()
629                 {
630                         var source = Read (12, 34, 56);
631                         Assert.That (source.First (), Is.EqualTo (12));
632                 }
633
634                 [Test]
635                 public void First_IntegersWithPredicateForEvens_FirstEvenInteger ()
636                 {
637                         var source = Read (15, 20, 25, 30);
638                         Assert.That (source.First (i => i % 2 == 0), Is.EqualTo (20));
639                 }
640
641                 [Test]
642                 [ExpectedException (typeof (InvalidOperationException))]
643                 public void First_IntegerSequenceWithNoneMatchingPredicate_ThrowsInvalidOperationException ()
644                 {
645                         var source = Read (12, 34, 56, 78);
646                         Assert.That (source.First (i => i > 100), Is.EqualTo (0));
647                 }
648
649                 [Test]
650                 public void FirstOrDefault_EmptyBooleanSource_ReturnsFalse ()
651                 {
652                         Assert.That (Read<bool> ().FirstOrDefault (), Is.False);
653                 }
654
655                 [Test]
656                 public void FirstOrDefault_Objects_ReturnsFirstReference ()
657                 {
658                         var first = new object ();
659                         var source = Read (first, new object ());
660                         Assert.That (source.FirstOrDefault (), Is.SameAs (first));
661                 }
662
663                 [Test]
664                 [ExpectedException (typeof (ArgumentNullException))]
665                 public void FirstOrDefault_PredicateArg_NullPredicate_ThrowsArgumentNullException ()
666                 {
667                         Read<int> ().FirstOrDefault (null);
668                 }
669
670                 [Test]
671                 public void FirstOrDefault_PredicateArg_NonNullPredicate_ReturnsFirstMatchingItem ()
672                 {
673                         var source = Read (1, 4, 8);
674                         Assert.That (source.FirstOrDefault (i => i % 2 == 0), Is.EqualTo (4));
675                 }
676
677                 [Test]
678                 public void FirstOrDefault_PredicateArg_IntegerSequenceWithNonMatchingPredicate_ReturnsDefaultValue ()
679                 {
680                         var source = Read (1, 4, 6);
681                         Assert.That (source.FirstOrDefault (i => i > 10), Is.EqualTo (0));
682                 }
683
684                 [Test]
685                 public void First_IntegerListOptimization_ReturnsFirstElementWithoutEnumerating ()
686                 {
687                         var source = new NonEnumerableList<int> (new [] { 123, 456, 789 });
688                         Assert.That (source.First (), Is.EqualTo (123));
689                 }
690
691                 private class Person {
692                         public string FirstName { get; set; }
693                         public string LastName { get; set; }
694                         public int Age { get; set; }
695
696                         public static Person [] CreatePersons ()
697                         {
698                                 return new []
699                 {
700                     new Person { LastName = "M\u00FCller", FirstName = "Peter",   Age = 21 },
701                     new Person { LastName = "M\u00FCller", FirstName = "Herbert", Age = 22 },
702                     new Person { LastName = "Meier",       FirstName = "Hubert",  Age = 23 },
703                     new Person { LastName = "Meier",       FirstName = "Isidor",  Age = 24 }
704                 };
705                         }
706
707                         public static Person [] CreatePersonsWithNamesUsingMixedCase ()
708                         {
709                                 var persons = CreatePersons ();
710                                 var herbert = persons [1];
711                                 herbert.LastName = herbert.LastName.ToLower ();
712                                 var isidor = persons [3];
713                                 isidor.LastName = isidor.LastName.ToLower ();
714                                 return persons;
715                         }
716                 }
717
718                 [Test]
719                 [ExpectedException (typeof (ArgumentNullException))]
720                 public void GroupBy_KeySelectorArg_NullAsKeySelector_ThrowsArgumentNullException ()
721                 {
722                         Read<object> ().GroupBy<object, object> (null);
723                 }
724
725                 [Test]
726                 public void GroupBy_KeySelectorArg_ValidArguments_CorrectGrouping ()
727                 {
728                         var persons = Read (Person.CreatePersons ());
729                         var result = new Reader<IGrouping<string, Person>> (persons.GroupBy (person => person.LastName));
730
731                         var group1 = result.Read ();
732                         Assert.That (group1.Key, Is.EqualTo ("M\u00FCller"));
733                         var muellers = new Reader<Person> (group1);
734                         Assert.That (muellers.Read ().FirstName, Is.EqualTo ("Peter"));
735                         Assert.That (muellers.Read ().FirstName, Is.EqualTo ("Herbert"));
736
737                         var group2 = result.Read ();
738                         Assert.That (group2.Key, Is.EqualTo ("Meier"));
739                         var meiers = new Reader<Person> (group2);
740                         Assert.That (meiers.Read ().FirstName, Is.EqualTo ("Hubert"));
741                         Assert.That (meiers.Read ().FirstName, Is.EqualTo ("Isidor"));
742
743                         result.AssertEnded ();
744                 }
745
746                 [Test]
747                 public void GroupBy_KeySelectorArg_ValidArguments_CorrectCaseSensitiveGrouping ()
748                 {
749                         var persons = Read (Person.CreatePersonsWithNamesUsingMixedCase ());
750
751                         var result = persons.GroupBy (person => person.LastName);
752
753                         var e = result.GetEnumerator ();
754                         Func<IGrouping<string, Person>, Person> first = g => new Reader<Person> (g).Read ();
755
756                         e.MoveNext ();
757                         Assert.That (e.Current.Key, Is.EqualTo ("M\u00FCller"));
758                         Assert.That (first (e.Current).FirstName, Is.EqualTo ("Peter"));
759
760                         e.MoveNext ();
761                         Assert.That (e.Current.Key, Is.EqualTo ("m\u00FCller"));
762                         Assert.That (first (e.Current).FirstName, Is.EqualTo ("Herbert"));
763
764                         e.MoveNext ();
765                         Assert.That (e.Current.Key, Is.EqualTo ("Meier"));
766                         Assert.That (first (e.Current).FirstName, Is.EqualTo ("Hubert"));
767
768                         e.MoveNext ();
769                         Assert.That (e.Current.Key, Is.EqualTo ("meier"));
770                         Assert.That (first (e.Current).FirstName, Is.EqualTo ("Isidor"));
771
772                         Assert.That (e.MoveNext (), Is.False);
773                 }
774
775                 [Test]
776                 public void GroupBy_KeySelectorArgComparerArg_KeysThatDifferInCasingNonCaseSensitiveStringComparer_CorrectGrouping ()
777                 {
778                         var persons = Read (Person.CreatePersonsWithNamesUsingMixedCase ());
779
780                         var result = new Reader<IGrouping<string, Person>> (
781                                 persons.GroupBy (person => person.LastName, StringComparer.CurrentCultureIgnoreCase));
782
783                         var group1 = result.Read ();
784                         Assert.That (group1.Key, Is.EqualTo ("M\u00FCller"));
785                         var muellers = new Reader<Person> (group1);
786                         Assert.That (muellers.Read ().FirstName, Is.EqualTo ("Peter"));
787                         Assert.That (muellers.Read ().FirstName, Is.EqualTo ("Herbert"));
788
789                         var group2 = result.Read ();
790                         Assert.That (group2.Key, Is.EqualTo ("Meier"));
791                         var meiers = new Reader<Person> (group2);
792                         Assert.That (meiers.Read ().FirstName, Is.EqualTo ("Hubert"));
793                         Assert.That (meiers.Read ().FirstName, Is.EqualTo ("Isidor"));
794
795                         result.AssertEnded ();
796                 }
797
798                 [Test]
799                 public void GroupBy_KeySelectorArgElementSelectorArg_ValidArguments_CorrectGroupingAndProjection ()
800                 {
801                         var persons = Read (Person.CreatePersons ());
802
803                         var result = new Reader<IGrouping<string, int>> (
804                                 persons.GroupBy (person => person.LastName, person => person.Age));
805
806                         var group1 = result.Read ();
807                         Assert.That (group1.Key, Is.EqualTo ("M\u00FCller"));
808                         var muellers = new Reader<int> (group1);
809                         Assert.That (muellers.Read (), Is.EqualTo (21));
810                         Assert.That (muellers.Read (), Is.EqualTo (22));
811
812                         var group2 = result.Read ();
813                         Assert.That (group2.Key, Is.EqualTo ("Meier"));
814                         var meiers = new Reader<int> (group2);
815                         Assert.That (meiers.Read (), Is.EqualTo (23));
816                         Assert.That (meiers.Read (), Is.EqualTo (24));
817                 }
818
819                 [Test]
820                 public void GroupBy_KeySelectorArgResultSelectorArg_ValidArguments_CorrectGroupingProcessing ()
821                 {
822                         var persons = Read (Person.CreatePersons ());
823
824                         var result = persons.GroupBy (
825                                                          p => p.LastName,
826                                                          (key, group) => {
827                                                                  var total = 0;
828                                                                  foreach (var p in group)
829                                                                          total += p.Age;
830                                                                  return key + ":" + total;
831                                                          });
832
833                         result.AssertEquals ("M\u00FCller:43", "Meier:47");
834                 }
835
836                 [Test]
837                 public void GroupBy_KeySelectorArgElementSelectorArgComparerArg_ValidArguments_CorrectGroupingAndProcessing ()
838                 {
839                         var persons = Read (Person.CreatePersonsWithNamesUsingMixedCase ());
840
841                         var result = new Reader<IGrouping<string, int>> (
842                                 persons.GroupBy (p => p.LastName, p => p.Age, StringComparer.CurrentCultureIgnoreCase));
843
844                         var group1 = result.Read ();
845                         Assert.That (group1.Key, Is.EqualTo ("M\u00FCller"));
846                         var muellers = new Reader<int> (group1);
847                         Assert.That (muellers.Read (), Is.EqualTo (21));
848                         Assert.That (muellers.Read (), Is.EqualTo (22));
849
850                         var group2 = result.Read ();
851                         Assert.That (group2.Key, Is.EqualTo ("Meier"));
852                         var meiers = new Reader<int> (group2);
853                         Assert.That (meiers.Read (), Is.EqualTo (23));
854                         Assert.That (meiers.Read (), Is.EqualTo (24));
855                 }
856
857                 [Test]
858                 public void GroupBy_KeySelectorArgElementSelectorArgResultSelectorArg_ValidArguments_CorrectGroupingAndTransforming ()
859                 {
860                         var persons = Read (Person.CreatePersons ());
861
862                         var result = persons.GroupBy (
863                                                          p => p.LastName,
864                                                          p => p.Age,
865                                                          (key, ages) => {
866                                                                  var total = 0;
867                                                                  foreach (var age in ages)
868                                                                          total += age;
869                                                                  return key + ":" + total;
870                                                          });
871
872                         result.AssertEquals ("M\u00FCller:43", "Meier:47");
873                 }
874
875                 [Test]
876                 public void GroupBy_KeySelectorArgResultSelectorArgComparerArg_ValidArguments_CorrectGroupingAndTransforming ()
877                 {
878                         var persons = Read (Person.CreatePersonsWithNamesUsingMixedCase ());
879
880                         var result = persons.GroupBy (
881                                                          p => p.LastName,
882                                                          (key, values) => {
883                                                                  var total = 0;
884                                                                  foreach (var person in values)
885                                                                          total += person.Age;
886                                                                  return key + ":" + total;
887                                                          },
888                                                          StringComparer.CurrentCultureIgnoreCase);
889
890                         result.AssertEquals ("M\u00FCller:43", "Meier:47");
891                 }
892
893                 [Test]
894                 public void GroupBy_KeySelectorArgElementSelectorArgResultSelectorArgComparerArg_ValidArguments_CorrectGroupingAndTransforming ()
895                 {
896                         var persons = Read (Person.CreatePersonsWithNamesUsingMixedCase ());
897
898                         var result = persons.GroupBy (
899                                                          p => p.LastName,
900                                                          p => p.Age,
901                                                          (key, ages) => {
902                                                                  var total = 0;
903                                                                  foreach (var age in ages)
904                                                                          total += age;
905                                                                  return key + ":" + total;
906                                                          },
907                                                          StringComparer.CurrentCultureIgnoreCase);
908
909                         result.AssertEquals ("M\u00FCller:43", "Meier:47");
910                 }
911
912                 class Pet {
913                         public string Name { get; set; }
914                         public string Owner { get; set; }
915                 }
916
917                 [Test]
918                 public void GroupJoin_InnerArgOuterKeySelectorArgInnerKeySelectorArgResultSelectorArg_ValidArguments_CorrectGroupingAndJoining ()
919                 {
920                         var persons = Read (Person.CreatePersons ());
921
922                         var barley = new Pet { Name = "Barley", Owner = "Peter" };
923                         var boots = new Pet { Name = "Boots", Owner = "Herbert" };
924                         var whiskers = new Pet { Name = "Whiskers", Owner = "Herbert" };
925                         var daisy = new Pet { Name = "Daisy", Owner = "Isidor" };
926
927                         var pets = Read (barley, boots, whiskers, daisy);
928
929                         var result = persons.GroupJoin (pets, person => person.FirstName, pet => pet.Owner,
930                                                           (person, ppets) => new { Owner = person, Pets = ppets });
931
932                         using (var e = result.GetEnumerator ()) {
933                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Peter"));
934                                 e.Current.Pets.AssertThat (Is.SameAs, barley);
935
936                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Herbert"));
937                                 e.Current.Pets.AssertThat (Is.SameAs, boots, whiskers);
938
939                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Hubert"));
940                                 e.Current.Pets.AssertThat (Is.SameAs); // empty
941
942                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Isidor"));
943                                 e.Current.Pets.AssertThat (Is.SameAs, daisy);
944
945                                 Assert.That (e.MoveNext (), Is.False);
946                         }
947                 }
948
949                 [Test]
950                 public void GroupJoin_InnerArgOuterKeySelectorArgInnerKeySelectorArgResultSelectorArgComparerArg_ValidArguments_CorrectGroupingAndJoining ()
951                 {
952                         var persons = Read (Person.CreatePersons ());
953
954                         var barley = new Pet { Name = "Barley", Owner = "Peter" };
955                         var boots = new Pet { Name = "Boots", Owner = "Herbert" };
956                         var whiskers = new Pet { Name = "Whiskers", Owner = "HeRbErT" };
957                         var daisy = new Pet { Name = "Daisy", Owner = "Isidor" };
958
959                         var pets = Read (barley, boots, whiskers, daisy);
960
961                         var result = persons.GroupJoin (pets, person => person.FirstName, pet => pet.Owner,
962                                                           (person, ppets) => new { Owner = person, Pets = ppets },
963                                                           StringComparer.CurrentCultureIgnoreCase);
964
965                         using (var e = result.GetEnumerator ()) {
966                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Peter"));
967                                 e.Current.Pets.AssertThat (Is.SameAs, barley);
968
969                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Herbert"));
970                                 e.Current.Pets.AssertThat (Is.SameAs, boots, whiskers);
971
972                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Hubert"));
973                                 e.Current.Pets.AssertThat (Is.SameAs); // empty
974
975                                 e.MoveNext (); Assert.That (e.Current.Owner.FirstName, Is.EqualTo ("Isidor"));
976                                 e.Current.Pets.AssertThat (Is.SameAs, daisy);
977
978                                 Assert.That (e.MoveNext (), Is.False);
979                         }
980                 }
981
982                 [Test]
983                 [ExpectedException (typeof (ArgumentNullException))]
984                 public void GroupJoin_InnerArgOuterKeySelectorArgInnerKeySelectorArgResultSelectorArg_NullOuterKeySelector_ThrowsArgumentNullException ()
985                 {
986                         new object [0].GroupJoin<object, object, object, object> (
987                                 new object [0], null,
988                                 delegate { throw new NotImplementedException (); },
989                                 delegate { throw new NotImplementedException (); });
990                 }
991
992                 [Test]
993                 [ExpectedException (typeof (ArgumentNullException))]
994                 public void Intersect_NullSecondSource_ThrowsArgumentNullException ()
995                 {
996                         Read<object> ().Intersect (null);
997                 }
998
999                 [Test]
1000                 public void Intersect_IntegerSources_YieldsCommonSet ()
1001                 {
1002                         var first = Read (1, 2, 3);
1003                         var second = Read (2, 3, 4);
1004                         first.Intersect (second).AssertEquals (2, 3);
1005                 }
1006
1007                 [Test]
1008                 public void Intersect_MixedStringsAndCaseInsensitiveComparer_YieldsCommonSetFromFirstSource ()
1009                 {
1010                         var first = Read ("Heinrich", "Hubert", "Thomas");
1011                         var second = Read ("Heinrich", "hubert", "Joseph");
1012                         var result = first.Intersect (second, StringComparer.CurrentCultureIgnoreCase);
1013                         result.AssertEquals ("Heinrich", "Hubert");
1014                 }
1015
1016                 [Test]
1017                 [ExpectedException (typeof (ArgumentNullException))]
1018                 public void Join_InnerArgOuterKeySelectorArgInnerKeySelectorArgResultSelectorArg_PassNullAsArgument_ThrowsArgumentNullException ()
1019                 {
1020                         Read<object> ().Join<object, object, object, object> (null, null, null, null);
1021                 }
1022
1023                 [Test]
1024                 public void Join_InnerArgOuterKeySelectorArgInnerKeySelectorArgResultSelectorArg_PassingPetsAndOwners_PetsAreCorrectlyAssignedToOwners ()
1025                 {
1026                         var persons = Read (Person.CreatePersons ());
1027
1028                         var pets = new Reader<Pet> (new []
1029                            {
1030                                new Pet {Name = "Barley", Owner = "Peter"},
1031                                new Pet {Name = "Boots", Owner = "Herbert"},
1032                                new Pet {Name = "Whiskers", Owner = "Herbert"},
1033                                new Pet {Name = "Daisy", Owner = "Isidor"}
1034                            });
1035
1036                         var result = persons.Join (pets, aPerson => aPerson.FirstName, aPet => aPet.Owner,
1037                                                  (aPerson, aPet) => new { Owner = aPerson.FirstName, Pet = aPet.Name });
1038
1039                         var e = result.GetEnumerator ();
1040
1041                         Assert.That (e.MoveNext (), Is.True);
1042                         Assert.That (e.Current.Owner, Is.EqualTo ("Peter"));
1043                         Assert.That (e.Current.Pet, Is.EqualTo ("Barley"));
1044
1045                         Assert.That (e.MoveNext (), Is.True);
1046                         Assert.That (e.Current.Owner, Is.EqualTo ("Herbert"));
1047                         Assert.That (e.Current.Pet, Is.EqualTo ("Boots"));
1048
1049                         Assert.That (e.MoveNext (), Is.True);
1050                         Assert.That (e.Current.Owner, Is.EqualTo ("Herbert"));
1051                         Assert.That (e.Current.Pet, Is.EqualTo ("Whiskers"));
1052
1053                         Assert.That (e.MoveNext (), Is.True);
1054                         Assert.That (e.Current.Owner, Is.EqualTo ("Isidor"));
1055                         Assert.That (e.Current.Pet, Is.EqualTo ("Daisy"));
1056
1057                         Assert.That (e.MoveNext (), Is.False);
1058                 }
1059
1060                 [Test]
1061                 public void Join_InnerArgOuterKeySelectorArgInnerKeySelectorArgResultSelectorArgComparerArg_PetOwnersNamesCasingIsInconsistent_CaseInsensitiveJoinIsPerformed ()
1062                 {
1063                         var persons = Read (Person.CreatePersons ());
1064
1065                         var pets = new Reader<Pet> (new []
1066                            {
1067                                new Pet {Name = "Barley", Owner = "Peter"},
1068                                new Pet {Name = "Boots", Owner = "Herbert"},
1069                                new Pet {Name = "Whiskers", Owner = "herbert"},
1070                                new Pet {Name = "Daisy", Owner = "Isidor"}
1071                            });
1072                         var result = persons.Join (pets, aPerson => aPerson.FirstName, aPet => aPet.Owner,
1073                                                  (aPerson, aPet) => new { Owner = aPerson.FirstName, Pet = aPet.Name },
1074                                                  StringComparer.CurrentCultureIgnoreCase);
1075
1076                         var e = result.GetEnumerator ();
1077
1078                         Assert.That (e.MoveNext (), Is.True);
1079                         Assert.That (e.Current.Owner, Is.EqualTo ("Peter"));
1080                         Assert.That (e.Current.Pet, Is.EqualTo ("Barley"));
1081
1082                         Assert.That (e.MoveNext (), Is.True);
1083                         Assert.That (e.Current.Owner, Is.EqualTo ("Herbert"));
1084                         Assert.That (e.Current.Pet, Is.EqualTo ("Boots"));
1085
1086                         Assert.That (e.MoveNext (), Is.True);
1087                         Assert.That (e.Current.Owner, Is.EqualTo ("Herbert"));
1088                         Assert.That (e.Current.Pet, Is.EqualTo ("Whiskers"));
1089
1090                         Assert.That (e.MoveNext (), Is.True);
1091                         Assert.That (e.Current.Owner, Is.EqualTo ("Isidor"));
1092                         Assert.That (e.Current.Pet, Is.EqualTo ("Daisy"));
1093
1094                         Assert.That (e.MoveNext (), Is.False);
1095                 }
1096
1097                 [Test]
1098                 public void Last_Integers_ReturnsLastElement ()
1099                 {
1100                         var source = Read (1, 2, 3);
1101                         Assert.That (source.Last (), Is.EqualTo (3));
1102                 }
1103
1104                 [Test]
1105                 public void Last_IntegerListOptimization_ReturnsLastElementWithoutEnumerating ()
1106                 {
1107                         var source = new NonEnumerableList<int> (new [] { 1, 2, 3 });
1108                         Assert.That (source.Last (), Is.EqualTo (3));
1109                 }
1110
1111                 [Test]
1112                 [ExpectedException (typeof (InvalidOperationException))]
1113                 public void Last_EmptyIntegerListOptimization_ThrowsInvalidOperationException ()
1114                 {
1115                         new NonEnumerableList<int> ().Last ();
1116                 }
1117
1118                 [Test]
1119                 [ExpectedException (typeof (ArgumentNullException))]
1120                 public void Last_PredicateArg_NullAsPredicate_ThrowsArgumentNullException ()
1121                 {
1122                         Read<object> ().Last (null);
1123                 }
1124
1125                 [Test]
1126                 [ExpectedException (typeof (InvalidOperationException))]
1127                 public void Last_PredicateArg_NoMatchingElement_ThrowsInvalidOperationException ()
1128                 {
1129                         var source = Read (1, 2, 3, 4, 5);
1130                         source.Last (i => i > 10);
1131                 }
1132
1133                 [Test]
1134                 public void Last_PredicateArg_ListOfInts_ReturnsLastMatchingElement ()
1135                 {
1136                         var source = Read (1, 2, 3, 4, 5);
1137                         Assert.That (source.Last (i => i % 2 == 0), Is.EqualTo (4));
1138                 }
1139
1140                 [Test]
1141                 public void LastOrDefault_EmptySource_ReturnsZero ()
1142                 {
1143                         var source = Read (new int [0]);
1144                         Assert.That (source.LastOrDefault (), Is.EqualTo (0));
1145                 }
1146
1147                 [Test]
1148                 public void LastOrDefault_NonEmptyList_ReturnsLastElement ()
1149                 {
1150                         var source = Read (1, 2, 3, 4, 5);
1151                         Assert.That (source.LastOrDefault (), Is.EqualTo (5));
1152                 }
1153
1154                 [Test]
1155                 public void LastOrDefault_PredicateArg_ValidArguments_RetunsLastMatchingElement ()
1156                 {
1157                         var source = Read (1, 2, 3, 4, 5);
1158                         Assert.That (source.LastOrDefault (i => i % 2 == 0), Is.EqualTo (4));
1159                 }
1160
1161                 [Test]
1162                 public void LastOrDefault_PredicateArg_NoMatchingElement_ReturnsZero ()
1163                 {
1164                         var source = Read (1, 3, 5, 7);
1165                         Assert.That (source.LastOrDefault (i => i % 2 == 0), Is.EqualTo (0));
1166                 }
1167
1168                 [Test]
1169                 public void LongCount_ValidArgument_ReturnsCorrectNumberOfElements ()
1170                 {
1171                         var source = Read (1, 4, 7, 10);
1172                         Assert.That (source.LongCount (), Is.EqualTo (4));
1173                 }
1174
1175                 [Test]
1176                 [ExpectedException (typeof (ArgumentNullException))]
1177                 public void LongCount_PredicateArg_NullAsPredicate_ThrowsArgumentNullException ()
1178                 {
1179                         Read<object> ().LongCount (null);
1180                 }
1181
1182                 [Test]
1183                 public void LongCount_PredicateArg_ValidArguments_ReturnsCorrectNumerOfMatchingElements ()
1184                 {
1185                         var source = Read (1, 2, 3, 4, 5);
1186                         Assert.That (source.LongCount (i => i % 2 == 0), Is.EqualTo (2));
1187                 }
1188
1189                 [Test]
1190                 [ExpectedException (typeof (InvalidOperationException))]
1191                 public void Max_EmptyList_ThrowsInvalidOperationException ()
1192                 {
1193                         var source = Read (new int [0]);
1194                         source.Max ();
1195                 }
1196
1197                 [Test]
1198                 public void Max_EmptyNullableIntegerArray_ReturnsNull ()
1199                 {
1200                         Assert.That (Read (new int? [0]).Max (), Is.Null);
1201                 }
1202
1203                 [Test]
1204                 public void Max_NullableIntegerArrayWithNullsOnly_ReturnsNull ()
1205                 {
1206                         Assert.That (Read<int?> (null, null, null).Max (), Is.Null);
1207                 }
1208
1209                 [Test]
1210                 public void Max_Integers_ReturnsMaxValue ()
1211                 {
1212                         var source = Read (1000, 203, -9999);
1213                         Assert.That (source.Max (), Is.EqualTo (1000));
1214                 }
1215
1216                 [Test]
1217                 public void Max_NullableLongs_ReturnsMaxValue ()
1218                 {
1219                         Assert.That (Read<long?> (1L, 2L, 3L, null).Max (), Is.EqualTo (3));
1220                 }
1221
1222                 [Test]
1223                 public void Max_NullableDoubles_ReturnsMaxValue ()
1224                 {
1225                         Assert.That (Read<double?> (1.0, 2.0, 3.0, null).Max (), Is.EqualTo (3));
1226                 }
1227
1228                 [Test]
1229                 public void Max_NullableDecimals_ReturnsMaxValue ()
1230                 {
1231                         Assert.That (Read<decimal?> (1m, 2m, 3m, null).Max (), Is.EqualTo (3));
1232                 }
1233
1234                 [Test]
1235                 public void Max_NullableFloats_ReturnsMaxValue ()
1236                 {
1237                         Assert.That (Read<float?> (-1000F, -100F, -1F, null).Max (), Is.EqualTo (-1));
1238                 }
1239
1240                 [Test]
1241                 public void Max_ListWithNullableType_ReturnsMaximum ()
1242                 {
1243                         var source = Read<int?> (1, 4, null, 10);
1244                         Assert.That (source.Max (), Is.EqualTo (10));
1245                 }
1246
1247                 [Test]
1248                 public void Max_NullableList_ReturnsMaxNonNullValue ()
1249                 {
1250                         var source = Read<int?> (-5, -2, null);
1251                         Assert.That (source.Max (), Is.EqualTo (-2));
1252                 }
1253
1254                 [Test]
1255                 public void Max_SelectorArg_ListOfObjects_ReturnsMaxSelectedValue ()
1256                 {
1257                         var persons = Read (Person.CreatePersons ());
1258                         Assert.That (persons.Max (p => p.Age), Is.EqualTo (24));
1259                 }
1260
1261                 [Test]
1262                 [ExpectedException (typeof (InvalidOperationException))]
1263                 public void Min_EmptyList_ThrowsInvalidOperationException ()
1264                 {
1265                         var source = Read<int> ();
1266                         source.Min ();
1267                 }
1268
1269                 [Test]
1270                 public void Min_IntegersWithSomeNull_ReturnsMinimumNonNullValue ()
1271                 {
1272                         var source = Read<int?> (199, 15, null, 30);
1273                         Assert.That (source.Min (), Is.EqualTo (15));
1274                 }
1275
1276                 [Test]
1277                 public void Min_NullableLongs_ReturnsMinimumNonNullValue ()
1278                 {
1279                         var source = Read<long?> (199L, 15L, null, 30L);
1280                         Assert.That (source.Min (), Is.EqualTo (15));
1281                 }
1282
1283                 [Test]
1284                 public void Min_NullableFloats_ReturnsMinimumNonNullValue ()
1285                 {
1286                         var source = Read<float?> (1.111F, null, 2.222F); // TODO Improve test data
1287                         Assert.That (source.Min (), Is.EqualTo (1.111F).Within (0.01));
1288                 }
1289
1290                 [Test]
1291                 public void Min_NullableDoubles_ReturnsMinimumNonNullValue ()
1292                 {
1293                         var source = Read<double?> (1.111, null, 2.222); // TODO Improve test data
1294                         Assert.That (source.Min (), Is.EqualTo (1.111).Within (0.01));
1295                 }
1296
1297                 [Test]
1298                 public void Min_NullableDecimals_ReturnsMinimumNonNullValue ()
1299                 {
1300                         var source = Read<decimal?> (1.111m, null, 2.222m);  // TODO Improve test data
1301                         Assert.That (source.Min (), Is.EqualTo (1.111m).Within (0.01));
1302                 }
1303
1304                 [Test]
1305                 public void Min_Chars_ReturnsMinimumBySortOrder ()
1306                 {
1307                         Assert.That ("qwertzuioplkjhgfdsayxcvbnm".ToCharArray ().Min (), Is.EqualTo ('a'));
1308                 }
1309
1310                 [Test]
1311                 public void Min_StringsWithLengthSelector_ReturnsMinimumNonNullStringLength ()
1312                 {
1313                         var strings = Read ("five", "four", null, "three", null, "two", "one", "zero");
1314                         Assert.That (strings.Min (s => s != null ? s.Length : (int?) null), Is.EqualTo (3));
1315                 }
1316
1317                 [Test]
1318                 public void OfType_EnumerableWithElementsOfDifferentTypes_OnlyDecimalsAreReturned ()
1319                 {
1320                         var source = Read<object> (1, "Hello", 1.234m, new object ());
1321                         var result = source.OfType<decimal> ();
1322                         result.AssertEquals (1.234m);
1323                 }
1324
1325                 [Test]
1326                 [ExpectedException (typeof (ArgumentNullException))]
1327                 public void OrderBy_KeySelectorArg_NullAsKeySelector_ThrowsArgumentNullException ()
1328                 {
1329                         Read<object> ().OrderBy<object, object> (null);
1330                 }
1331
1332                 [Test]
1333                 public void OrderBy_KeySelector_ArrayOfPersons_PersonsAreOrderedByAge ()
1334                 {
1335                         var persons = Person.CreatePersons ();
1336                         var reversePersons = (Person []) persons.Clone ();
1337                         Array.Reverse (reversePersons);
1338                         var source = Read (reversePersons);
1339                         var result = source.OrderBy (p => p.Age);
1340
1341                         var age = 21;
1342                         foreach (var person in result)
1343                                 Assert.That (person.Age, Is.EqualTo (age++));
1344
1345                         Assert.That (age, Is.EqualTo (25));
1346                 }
1347
1348                 [Test]
1349                 public void OrderBy_KeySelector_DataWithDuplicateKeys_YieldsStablySortedData ()
1350                 {
1351                         var data = new []
1352             {
1353                 new { Number = 4, Text = "four" },
1354                 new { Number = 4, Text = "quatre" },
1355                 new { Number = 4, Text = "vier" },
1356                 new { Number = 4, Text = "quattro" },
1357                 new { Number = 1, Text = "one" },
1358                 new { Number = 2, Text = "two" },
1359                 new { Number = 2, Text = "deux" },
1360                 new { Number = 3, Text = "three" },
1361                 new { Number = 3, Text = "trois" },
1362                 new { Number = 3, Text = "drei" },
1363             };
1364
1365                         var result = Read (data).OrderBy (e => e.Number);
1366                         using (var e = result.GetEnumerator ()) {
1367                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("one"));
1368                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("two"));
1369                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("deux"));
1370                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("three"));
1371                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("trois"));
1372                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("drei"));
1373                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("four"));
1374                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("quatre"));
1375                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("vier"));
1376                                 e.MoveNext (); Assert.That (e.Current.Text, Is.EqualTo ("quattro"));
1377                                 Assert.That (e.MoveNext (), Is.False);
1378                         }
1379                 }
1380
1381                 [Test]
1382                 public void ThenBy_KeySelector_DataWithDuplicateKeys_YieldsStablySortedData ()
1383                 {
1384                         var data = new []
1385             {
1386                 new { Position = 1, LastName = "Smith", FirstName = "John" },
1387                 new { Position = 2, LastName = "Smith", FirstName = "Jack" },
1388                 new { Position = 3, LastName = "Smith", FirstName = "John" },
1389                 new { Position = 4, LastName = "Smith", FirstName = "Jack" },
1390                 new { Position = 5, LastName = "Smith", FirstName = "John" },
1391                 new { Position = 6, LastName = "Smith", FirstName = "Jack" },
1392             };
1393
1394                         var result = Read (data).OrderBy (e => e.LastName).ThenBy (e => e.FirstName);
1395                         using (var e = result.GetEnumerator ()) {
1396                                 e.MoveNext (); Assert.That (e.Current.Position, Is.EqualTo (2));
1397                                 e.MoveNext (); Assert.That (e.Current.Position, Is.EqualTo (4));
1398                                 e.MoveNext (); Assert.That (e.Current.Position, Is.EqualTo (6));
1399                                 e.MoveNext (); Assert.That (e.Current.Position, Is.EqualTo (1));
1400                                 e.MoveNext (); Assert.That (e.Current.Position, Is.EqualTo (3));
1401                                 e.MoveNext (); Assert.That (e.Current.Position, Is.EqualTo (5));
1402                                 Assert.That (e.MoveNext (), Is.False);
1403                         }
1404                 }
1405
1406                 [Test]
1407                 [ExpectedException (typeof (ArgumentNullException))]
1408                 public void ThenBy_NullSource_ThrowsArgumentNullException ()
1409                 {
1410                         Enumerable.ThenBy<object, object> (null, delegate { throw new NotImplementedException (); });
1411                 }
1412
1413                 [Test]
1414                 [ExpectedException (typeof (ArgumentNullException))]
1415                 public void ThenBy_NullKeySelector_ThrowsArgumentNullException ()
1416                 {
1417                         Read<object> ().OrderBy<object, object> (e => { throw new NotImplementedException (); }).ThenBy<object, object> (null);
1418                 }
1419
1420                 [Test]
1421                 public void ThenByDescending_KeySelectorArgComparerArg_StringArray_CorrectOrdering ()
1422                 {
1423                         var source = Read ("AA", "AB", "AC", "-BA", "-BB", "-BC");
1424                         var result = source.OrderBy (s => s.ToCharArray () [s.ToCharArray ().Length - 1]).ThenByDescending (s => s.Length); /*.AssertEquals("butterfly", "elephant", "dog", "snake", "ape"); */
1425                         result.AssertEquals ("-BA", "AA", "-BB", "AB", "-BC", "AC");
1426                 }
1427
1428                 class ReverseComparer<T> : IComparer<T> where T : IComparable<T> {
1429                         public int Compare (T x, T y)
1430                         {
1431                                 return -1 * x.CompareTo (y);
1432                         }
1433                 }
1434
1435                 [Test]
1436                 public void OrderBy_KeySelectorArgComparerArg_ArrayOfPersonsAndReversecomparer_PersonsAreOrderedByAgeUsingReversecomparer ()
1437                 {
1438                         var persons = Read (Person.CreatePersons ());
1439                         var result = persons.OrderBy (p => p.Age, new ReverseComparer<int> ());
1440                         var age = 25;
1441                         foreach (var person in result) {
1442                                 age--;
1443                                 Assert.That (person.Age, Is.EqualTo (age));
1444                         }
1445                         Assert.That (age, Is.EqualTo (21));
1446
1447                 }
1448
1449                 [Test]
1450                 public void OrderByDescending_KeySelectorArg_ArrayOfPersons_PersonsAreOrderedByAgeDescending ()
1451                 {
1452                         var persons = Read (Person.CreatePersons ());
1453                         var result = persons.OrderByDescending (p => p.Age);
1454                         int age = 25;
1455                         foreach (var person in result) {
1456                                 age--;
1457                                 Assert.That (person.Age, Is.EqualTo (age));
1458                         }
1459                         Assert.That (age, Is.EqualTo (21));
1460                 }
1461
1462                 [Test]
1463                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
1464                 public void Range_ProduceRangeThatLeadsToOverflow_ThrowsArgumentOutOfRangeException ()
1465                 {
1466                         Enumerable.Range (int.MaxValue - 3, 5);
1467                 }
1468
1469                 [Test]
1470                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
1471                 public void Range_NegativeCount_ThrowsArgumentOutOfRangeException ()
1472                 {
1473                         Enumerable.Range (0, -1);
1474                 }
1475
1476                 [Test]
1477                 public void Range_Start10Count5_IntsFrom10To14 ()
1478                 {
1479                         var result = Enumerable.Range (10, 5);
1480                         result.AssertEquals (10, 11, 12, 13, 14);
1481                 }
1482
1483                 [Test]
1484                 [ExpectedException (typeof (ArgumentOutOfRangeException))]
1485                 public void Repeat_PassNegativeCount_ThrowsArgumentOutOfRangeException ()
1486                 {
1487                         Enumerable.Repeat ("Hello World", -2);
1488                 }
1489
1490                 [Test]
1491                 public void Repeat_StringArgumentCount2_ReturnValueContainsStringArgumentTwice ()
1492                 {
1493                         var result = Enumerable.Repeat ("Hello World", 2);
1494                         result.AssertEquals ("Hello World", "Hello World");
1495                 }
1496
1497                 [Test]
1498                 public void Reverse_SeriesOfInts_IntsAreCorrectlyReversed ()
1499                 {
1500                         var source = Read (1, 2, 3, 4, 5);
1501                         source.Reverse ().AssertEquals (5, 4, 3, 2, 1);
1502                 }
1503
1504                 [Test]
1505                 public void Select_ArrayOfPersons_AgeOfPersonsIsSelectedAccordingToPassedLambdaExpression ()
1506                 {
1507                         var persons = Read (Person.CreatePersons ());
1508                         persons.Select (p => p.Age).AssertEquals (21, 22, 23, 24);
1509                 }
1510
1511                 [Test]
1512                 public void Select_SelectorArg_LambdaThatTakesIndexAsArgument_ReturnValueContainsElementsMultipliedByIndex ()
1513                 {
1514                         var source = Read (0, 1, 2, 3);
1515                         source.Select ((i, index) => i * index).AssertEquals (0, 1, 4, 9);
1516                 }
1517
1518                 [Test]
1519                 public void SelectMany_SelectorArg_ArrayOfPersons_ReturnsASequenceWithAllLettersOfFirstnames ()
1520                 {
1521                         var persons = Read (Person.CreatePersons ());
1522                         var result = persons.SelectMany (p => p.FirstName.ToCharArray ());
1523                         var check = "PeterHerbertHubertIsidor".ToCharArray ();
1524                         int count = 0; // BUGBUG Collapse loop-based check with array assertion!
1525                         foreach (var c in result) {
1526                                 Assert.That (c, Is.EqualTo (check [count]));
1527                                 count++;
1528                         }
1529                 }
1530
1531                 class PetOwner {
1532                         public string Name { get; set; }
1533                         public IList<string> Pets { get; set; }
1534                 }
1535
1536                 [Test]
1537                 public void SelectMany_Selector3Arg_ArrayOfPetOwners_SelectorUsesElementIndexArgument ()
1538                 {
1539                         var petOwners = Read (new [] {
1540                   new PetOwner { Name = "Higa, Sidney",     Pets = new[] { "Scruffy", "Sam" } },
1541                   new PetOwner { Name = "Ashkenazi, Ronen", Pets = new[] { "Walker", "Sugar" } },
1542                   new PetOwner { Name = "Price, Vernette",  Pets = new[] { "Scratches", "Diesel" } },
1543                   new PetOwner { Name = "Hines, Patrick",   Pets = new[] { "Dusty" } } });
1544
1545                         var result = petOwners.SelectMany ((po, index) => po.Pets.Select (pet => index + pet));
1546
1547                         result.AssertEquals ("0Scruffy", "0Sam", "1Walker", "1Sugar", "2Scratches", "2Diesel", "3Dusty");
1548                 }
1549
1550                 [Test]
1551                 public void SelectMany_CollectionSelectorArgResultSelectorArg_ArrayOfPetOwner_ResultContainsElementForEachPetAPetOwnerHas ()
1552                 {
1553                         var petOwners = Read (new [] {
1554                   new PetOwner { Name = "Higa",      Pets = new[] { "Scruffy", "Sam" } },
1555                   new PetOwner { Name = "Ashkenazi", Pets = new[] { "Walker", "Sugar" } },
1556                   new PetOwner { Name = "Price",     Pets = new[] { "Scratches", "Diesel" } },
1557                   new PetOwner { Name = "Hines",     Pets = new[] { "Dusty" } } });
1558
1559                         var result = petOwners.SelectMany (po => po.Pets, (po, pet) => po.Name + "+" + pet);
1560
1561                         result.AssertEquals (
1562                                 "Higa+Scruffy", "Higa+Sam",
1563                                 "Ashkenazi+Walker", "Ashkenazi+Sugar",
1564                                 "Price+Scratches", "Price+Diesel",
1565                                 "Hines+Dusty");
1566                 }
1567
1568                 [Test]
1569                 [ExpectedException (typeof (ArgumentNullException))]
1570                 public void SequenceEqual_NullFirstSequence_ThrowsArgumentNullException ()
1571                 {
1572                         Enumerable.SequenceEqual (null, Read<object> ());
1573                 }
1574
1575                 [Test]
1576                 [ExpectedException (typeof (ArgumentNullException))]
1577                 public void SequenceEqual_NullSecondSequence_ThrowsArgumentNullException ()
1578                 {
1579                         Read<object> ().SequenceEqual (null);
1580                 }
1581
1582                 [Test]
1583                 public void SequenceEqual_EqualSequences_ReturnsTrue ()
1584                 {
1585                         var source = Read (1, 2, 3);
1586                         var argument = Read (1, 2, 3);
1587                         Assert.That (source.SequenceEqual (argument), Is.True);
1588                 }
1589
1590                 [Test]
1591                 public void SequenceEqual_DifferentSequences_ReturnsFalse ()
1592                 {
1593                         var source = Read (1, 2, 3);
1594                         var argument = Read (1, 3, 2);
1595                         Assert.That (source.SequenceEqual (argument), Is.False);
1596                 }
1597
1598                 [Test]
1599                 public void SequenceEqual_LongerSecondSequence_ReturnsFalse ()
1600                 {
1601                         var source = Read (1, 2, 3);
1602                         var argument = Read (1, 2, 3, 4);
1603                         Assert.That (source.SequenceEqual (argument), Is.False);
1604                 }
1605
1606                 [Test]
1607                 public void SequenceEqual_ShorterSecondSequence_ReturnsFalse ()
1608                 {
1609                         var first = Read (1, 2, 3, 4);
1610                         var second = Read (1, 2, 3);
1611                         Assert.That (first.SequenceEqual (second), Is.False);
1612                 }
1613
1614                 [Test]
1615                 public void SequenceEqual_FloatsWithTolerantComparer_ComparerIsUsed ()
1616                 {
1617                         var source = Read (1F, 2F, 3F);
1618                         var argument = Read (1.03F, 1.99F, 3.02F);
1619                         Assert.That (source.SequenceEqual (argument, new FloatComparer ()), Is.True);
1620                 }
1621
1622                 private sealed class FloatComparer : IEqualityComparer<float> {
1623                         public bool Equals (float x, float y)
1624                         {
1625                                 return Math.Abs (x - y) < 0.1f;
1626                         }
1627                         public int GetHashCode (float x)
1628                         {
1629                                 throw new NotImplementedException ();
1630                         }
1631                 }
1632
1633                 [Test]
1634                 [ExpectedException (typeof (InvalidOperationException))]
1635                 public void Single_EmptySource_ThrowsInvalidOperationException ()
1636                 {
1637                         var source = Read<int> ();
1638                         source.Single ();
1639                 }
1640
1641                 [Test]
1642                 [ExpectedException (typeof (InvalidOperationException))]
1643                 public void Single_SourceWithMoreThanOneElement_ThrowsInvalidOperationException ()
1644                 {
1645                         var source = Read (3, 6);
1646                         source.Single ();
1647                 }
1648
1649                 [Test]
1650                 public void Single_SourceWithOneElement_ReturnsSingleElement ()
1651                 {
1652                         var source = Read (1);
1653                         Assert.That (source.Single (), Is.EqualTo (1));
1654                 }
1655
1656                 [Test]
1657                 [ExpectedException (typeof (ArgumentNullException))]
1658                 public void Single_PredicateArg_PassNullAsPredicate_ThrowsArgumentNullException ()
1659                 {
1660                         Read<object> ().Single (null);
1661                 }
1662
1663                 [Test]
1664                 [ExpectedException (typeof (InvalidOperationException))]
1665                 public void Single_PredicateArg_NoElementSatisfiesCondition_ThrowsInvalidOperationException ()
1666                 {
1667                         var source = Read (1, 3, 5);
1668                         source.Single (i => i % 2 == 0);
1669                 }
1670
1671                 [Test]
1672                 [ExpectedException (typeof (InvalidOperationException))]
1673                 public void Single_PredicateArg_MoreThanOneElementSatisfiedCondition_ThrowsInvalidOperationException ()
1674                 {
1675                         var source = Read (1, 2, 3, 4);
1676                         source.Single (i => i % 2 == 0);
1677                 }
1678
1679                 [Test]
1680                 [ExpectedException (typeof (InvalidOperationException))]
1681                 public void Single_PredicateArg_SourceIsEmpty_ThrowsInvalidOperationException ()
1682                 {
1683                         var source = Read<int> ();
1684                         source.Single (i => i % 2 == 0);
1685                 }
1686
1687                 [Test]
1688                 public void Single_PredicateArg_ArrayOfIntWithOnlyOneElementSatisfyingCondition_ReturnsOnlyThisElement ()
1689                 {
1690                         var source = Read (1, 2, 3);
1691                         Assert.That (source.Single (i => i % 2 == 0), Is.EqualTo (2));
1692                 }
1693
1694                 [Test]
1695                 [ExpectedException (typeof (InvalidOperationException))]
1696                 public void SingleOrDefault_MoreThanOneElementInSource_ThrowsInvalidOperationException ()
1697                 {
1698                         var source = Read (1, 2, 3);
1699                         source.SingleOrDefault ();
1700                 }
1701
1702                 [Test]
1703                 public void SingleOrDefault_EmptySource_ReturnsZero ()
1704                 {
1705                         var source = Read<int> ();
1706                         Assert.That (source.SingleOrDefault (), Is.EqualTo (0));
1707                 }
1708
1709                 [Test]
1710                 public void SingleOrDefault_SourceWithOneElement_ReturnsSingleElement ()
1711                 {
1712                         var source = Read (5);
1713                         Assert.That (source.SingleOrDefault (), Is.EqualTo (5));
1714                 }
1715
1716                 [Test]
1717                 [ExpectedException (typeof (ArgumentNullException))]
1718                 public void SingleOrDefault_PredicateArg_PassNullAsPredicate_ThrowsArgumentNullException ()
1719                 {
1720                         Read<object> ().SingleOrDefault (null);
1721                 }
1722
1723                 [Test]
1724                 public void SingleOrDefault_PredicateArg_EmptySource_ReturnsZero ()
1725                 {
1726                         var source = Read<int> ();
1727                         Assert.That (source.SingleOrDefault (i => i % 2 == 0), Is.EqualTo (0));
1728                 }
1729
1730                 [Test]
1731                 [ExpectedException (typeof (InvalidOperationException))]
1732                 public void SingleOrDefault_PredicateArg_MoreThanOneElementSatisfiesCondition_ThrowsInvalidOperationException ()
1733                 {
1734                         var source = Read (1, 2, 3, 4, 5);
1735                         source.SingleOrDefault (i => i % 2 == 0);
1736                 }
1737
1738                 [Test]
1739                 public void SingleOrDefault_PredicateArg_NoElementSatisfiesCondition_ReturnsZero ()
1740                 {
1741                         var source = Read (1, 3, 5);
1742                         Assert.That (source.SingleOrDefault (i => i % 2 == 0), Is.EqualTo (0));
1743                 }
1744
1745                 [Test]
1746                 public void SingleOrDefault_PredicateArg_OneElementSatisfiesCondition_ReturnsCorrectElement ()
1747                 {
1748                         var source = Read (1, 2, 3);
1749                         Assert.That (source.SingleOrDefault (i => i % 2 == 0), Is.EqualTo (2));
1750                 }
1751
1752                 [Test]
1753                 public void Skip_IntsFromOneToTenAndFifeAsSecondArg_IntsFromSixToTen ()
1754                 {
1755                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1756                         source.Skip (5).AssertEquals (6, 7, 8, 9, 10);
1757                 }
1758
1759                 [Test]
1760                 public void Skip_PassNegativeValueAsCount_SameBehaviorAsMicrosoftImplementation ()
1761                 {
1762                         var source = Read (1, 2, 3, 4, 5);
1763                         source.Skip (-5).AssertEquals (1, 2, 3, 4, 5);
1764                 }
1765
1766                 [Test]
1767                 [ExpectedException (typeof (ArgumentNullException))]
1768                 public void SkipWhile_PredicateArg_PassNullAsPredicate_ThrowsArgumentNullException ()
1769                 {
1770                         Read<object> ().SkipWhile ((Func<object, bool>) null);
1771                 }
1772
1773                 [Test]
1774                 public void SkipWhile_PredicateArg_IntsFromOneToFive_ElementsAreSkippedAsLongAsConditionIsSatisfied ()
1775                 {
1776                         var source = Read (1, 2, 3, 4, 5);
1777                         source.SkipWhile (i => i < 3).AssertEquals (3, 4, 5);
1778                 }
1779
1780                 [Test]
1781                 public void SkipWhile_PredicateArg_ArrayOfIntsWithElementsNotSatisfyingConditionAtTheEnd_IntsAtTheEndArePartOfResult ()
1782                 {
1783                         var source = Read (1, 2, 3, 4, 5, 1, 2, 3);
1784                         source.SkipWhile (i => i < 3).AssertEquals (3, 4, 5, 1, 2, 3);
1785                 }
1786
1787                 [Test]
1788                 public void SkipWhile_PredicateArg_PredicateAlwaysTrue_EmptyResult ()
1789                 {
1790                         var source = Read (1, 2, 3);
1791                         var result = source.SkipWhile (i => true);
1792                         Assert.That (result.GetEnumerator ().MoveNext (), Is.False);
1793                 }
1794
1795                 [Test]
1796                 public void SkipWhile_Predicate3Arg_IntsFromOneToNine_ElementsAreSkippedWhileIndexLessThanFive ()
1797                 {
1798                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9);
1799                         source.SkipWhile ((i, index) => index < 5).AssertEquals (6, 7, 8, 9);
1800                 }
1801
1802                 [Test]
1803                 [ExpectedException (typeof (OverflowException))]
1804                 public void Sum_SumOfArgumentsCausesOverflow_ThrowsOverflowException ()
1805                 {
1806                         var source = Read (int.MaxValue - 1, 2);
1807                         source.Sum ();
1808                 }
1809
1810                 [Test]
1811                 public void Sum_IntsFromOneToTen_ResultIsFiftyFive ()
1812                 {
1813                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1814                         Assert.That (source.Sum (), Is.EqualTo (55));
1815                 }
1816
1817                 [Test]
1818                 public void Sum_Longs_ReturnsSum ()
1819                 {
1820                         Assert.That (Read (1L, 2L, 3L).Sum (), Is.EqualTo (6));
1821                 }
1822
1823                 [Test]
1824                 public void Sum_SelectorArg_Longs_ReturnsSum ()
1825                 {
1826                         Assert.That (Read (123L, 456L, 789L).Sum (n => n * 2L), Is.EqualTo (2736L));
1827                 }
1828
1829                 [Test]
1830                 public void Sum_SelectorArg_NullableLongsWithSomeNulls_ReturnsSum ()
1831                 {
1832                         Assert.That (Read<long?> (123L, null, 456L, null, 789L).Sum (n => n * 2L), Is.EqualTo (2736L));
1833                 }
1834
1835                 [Test]
1836                 public void Sum_Floats_ReturnsSum ()
1837                 {
1838                         Assert.That (Read (1F, 2F, 3F).Sum (), Is.EqualTo (6));
1839                 }
1840
1841                 [Test]
1842                 public void Sum_SelectorArg_Floats_ReturnsSum ()
1843                 {
1844                         Assert.That (Read (123.4F, 567.8F, 91011.12F).Sum (n => n * 2.5F), Is.EqualTo (229255.8F));
1845                 }
1846
1847                 [Test]
1848                 public void Sum_NullableFloats_ReturnsSum ()
1849                 {
1850                         Assert.That (Read<float?> (1F, 2F, 3F, null).Sum (), Is.EqualTo (6));
1851                 }
1852
1853                 [Test]
1854                 public void Sum_SelectorArg_NullableFloatsWithSomeNulls_ReturnsSum ()
1855                 {
1856                         Assert.That (Read<float?> (123.4F, null, 567.8F, null, 91011.12F).Sum (n => n * 2.5F), Is.EqualTo (229255.8F));
1857                 }
1858
1859                 [Test]
1860                 public void Sum_Doubles_ReturnsSum ()
1861                 {
1862                         Assert.That (Read (1.0, 2.0, 3.0).Sum (), Is.EqualTo (6));
1863                 }
1864
1865                 [Test]
1866                 public void Sum_SelectorArg_Doubles_ReturnsSum ()
1867                 {
1868                         Assert.That (Read (123.4, 567.8, 91011.12).Sum (n => n * 2.5), Is.EqualTo (229255.8));
1869                 }
1870
1871                 [Test]
1872                 public void Sum_NullableDoubles_ReturnsSum ()
1873                 {
1874                         Assert.That (Read<double?> (1.0, 2.0, 3.0, null).Sum (), Is.EqualTo (6)); // TODO Improve test data
1875                 }
1876
1877                 [Test]
1878                 public void Sum_SelectorArg_NullableDoublesWithSomeNulls_ReturnsSum ()
1879                 {
1880                         Assert.That (Read<double?> (123.4, null, 567.8, null, 91011.12).Sum (n => n * 2.5), Is.EqualTo (229255.8));
1881                 }
1882
1883                 [Test]
1884                 public void Sum_Decimals_ReturnsSum ()
1885                 {
1886                         Assert.That (Read (1m, 2m, 3m).Sum (), Is.EqualTo (6));
1887                 }
1888
1889                 [Test]
1890                 public void Sum_SelectorArg_Decimals_ReturnsSum ()
1891                 {
1892                         Assert.That (Read (123.4m, 567.8m, 91011.12m).Sum (n => n * 2.5m), Is.EqualTo (229255.8m));
1893                 }
1894
1895                 [Test]
1896                 public void Sum_NullableDecimals_ReturnsSum ()
1897                 {
1898                         Assert.That (Read<decimal?> (1m, 2m, 3m, null).Sum (), Is.EqualTo (6)); // TODO Improve test data
1899                 }
1900
1901                 [Test]
1902                 public void Sum_SelectorArg_NullableDecimalsWithSomeNulls_ReturnsSum ()
1903                 {
1904                         Assert.That (Read<decimal?> (123.4m, null, 567.8m, null, 91011.12m).Sum (n => n * 2.5m), Is.EqualTo (229255.8m));
1905                 }
1906
1907                 [Test]
1908                 public void Sum_NullableLongs_ReturnsSum ()
1909                 {
1910                         Assert.That (Read<long?> (1L, 2L, 3L, null).Sum (), Is.EqualTo (6)); // TODO Improve test data
1911                 }
1912
1913                 [Test]
1914                 public void Sum_NullableIntsAsArguments_ReturnsCorrectSum () // TODO Improve test data
1915                 {
1916                         var source = Read<int?> (1, 2, null);
1917                         Assert.That (source.Sum (), Is.EqualTo (3));
1918                 }
1919
1920                 [Test]
1921                 public void Sum_SelectorArgNullableIntegersWithSomeNulls_ReturnsSum ()
1922                 {
1923                         var source = Read<int?> (123, null, 456, null, 789);
1924                         Assert.That (source.Sum (n => n * 2), Is.EqualTo (2736));
1925                 }
1926
1927                 [Test]
1928                 public void Sum_SelectorArg_StringArray_ResultIsSumOfStringLengths ()
1929                 {
1930                         var source = Read ("dog", "cat", "eagle");
1931                         Assert.That (source.Sum (s => s.Length), Is.EqualTo (11));
1932                 }
1933
1934                 [Test]
1935                 public void Take_IntsFromOneToSixAndThreeAsCount_IntsFromOneToThreeAreReturned ()
1936                 {
1937                         var source = Read (1, 2, 3, 4, 5, 6);
1938                         source.Take (3).AssertEquals (1, 2, 3);
1939                 }
1940
1941                 [Test]
1942                 public void Take_CountBiggerThanList_ReturnsAllElements ()
1943                 {
1944                         var source = Read (1, 2, 3, 4, 5);
1945                         source.Take (10).AssertEquals (1, 2, 3, 4, 5);
1946                 }
1947
1948                 [Test]
1949                 [ExpectedException (typeof (ArgumentNullException))]
1950                 public void TakeWhile_PassNullAsPredicate_ThrowsArgumentNullException ()
1951                 {
1952                         new object [0].TakeWhile ((Func<object, bool>) null);
1953                 }
1954
1955                 [Test]
1956                 public void TakeWhile_IntsFromOneToTenAndConditionThatSquareIsSmallerThan50_IntsFromOneToSeven ()
1957                 {
1958                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1959                         source.TakeWhile (i => i * i < 50).AssertEquals (1, 2, 3, 4, 5, 6, 7);
1960                 }
1961
1962                 [Test]
1963                 public void ToArray_IntsFromOneToTen_ResultIsIntArrayContainingAllElements ()
1964                 {
1965                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1966                         var result = source.ToArray ();
1967                         Assert.That (result, Is.TypeOf (typeof (int [])));
1968                         result.AssertEquals (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
1969                 }
1970
1971                 [Test]
1972                 [ExpectedException (typeof (ArgumentNullException))]
1973                 public void ToDictionary_KeySelectorArg_KeySelectorYieldsNull_ThrowsArgumentNullException ()
1974                 {
1975                         var source = new [] { "eagle", "deer" };
1976                         source.ToDictionary<string, string> (s => null);
1977                 }
1978
1979                 [Test]
1980                 [ExpectedException (typeof (ArgumentException))]
1981                 public void ToDictionary_KeySelectorArg_DuplicateKeys_ThrowsArgumentException ()
1982                 {
1983                         var source = new [] { "eagle", "deer", "cat", "dog" };
1984                         source.ToDictionary (s => s.Length);
1985                 }
1986
1987                 [Test]
1988                 public void ToDictionary_KeySelectorArg_ValidArguments_KeySelectorIsUsedForKeysInDictionary ()
1989                 {
1990                         var source = Read ("1", "2", "3");
1991                         var result = source.ToDictionary (s => int.Parse (s));
1992                         int check = 1;
1993                         foreach (var pair in result) {
1994                                 Assert.That (pair.Key, Is.EqualTo (check));
1995                                 Assert.That (pair.Value, Is.EqualTo (check.ToString ()));
1996                                 check++;
1997                         }
1998                         Assert.That (check, Is.EqualTo (4));
1999                 }
2000
2001                 [Test]
2002                 public void ToDictionary_KeySelectorArgElementSelectorArg_IntsFromOneToTen_KeySelectorAndElementSelectorAreUsedForDictionaryElements ()
2003                 {
2004                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
2005                         var result = source.ToDictionary (i => i.ToString (), i => Math.Sqrt (double.Parse (i.ToString ())));
2006                         int check = 1;
2007                         foreach (var pair in result) {
2008                                 Assert.That (pair.Key, Is.EqualTo (check.ToString ()));
2009                                 Assert.That (pair.Value, Is.EqualTo (Math.Sqrt (double.Parse (check.ToString ()))).Within (0.00001));
2010                                 check++;
2011                         }
2012                 }
2013
2014                 [Test]
2015                 public void ToList_IntsFromOneToTen_ReturnsListOfIntsContainingAllElements ()
2016                 {
2017                         var source = Read (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
2018                         var result = source.ToList ();
2019                         Assert.That (result, Is.TypeOf (typeof (List<int>)));
2020                         result.AssertEquals (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
2021                 }
2022
2023                 [Test]
2024                 public void ToLookup_KeySelectorArg_Strings_StringsByLength ()
2025                 {
2026                         var source = Read ("eagle", "dog", "cat", "bird", "camel");
2027                         var lookup = source.ToLookup (s => s.Length);
2028
2029                         Assert.That (lookup.Count, Is.EqualTo (3));
2030
2031                         Assert.That (lookup.Contains (3), Is.True);
2032                         lookup [3].AssertEquals ("dog", "cat");
2033
2034                         Assert.That (lookup.Contains (4), Is.True);
2035                         lookup [4].AssertEquals ("bird");
2036
2037                         Assert.That (lookup.Contains (5), Is.True);
2038                         lookup [5].AssertEquals ("eagle", "camel");
2039                 }
2040
2041                 [Test]
2042                 public void ToLookup_KeySelectorArgElementSelectorArg_Strings_ProjecetedStringsByLength ()
2043                 {
2044                         var source = Read ("eagle", "dog", "cat", "bird", "camel");
2045                         var lookup = source.ToLookup (s => s.Length, str => str.ToUpperInvariant ());
2046
2047                         Assert.That (lookup.Count, Is.EqualTo (3));
2048
2049                         Assert.That (lookup.Contains (3), Is.True);
2050                         var e = lookup [3].GetEnumerator ();
2051                         e.MoveNext (); Assert.That (e.Current, Is.EqualTo ("DOG"));
2052                         e.MoveNext (); Assert.That (e.Current, Is.EqualTo ("CAT"));
2053                         Assert.That (e.MoveNext (), Is.False);
2054
2055                         Assert.That (lookup.Contains (4), Is.True);
2056                         e = lookup [4].GetEnumerator ();
2057                         e.MoveNext (); Assert.That (e.Current, Is.EqualTo ("BIRD"));
2058                         Assert.That (e.MoveNext (), Is.False);
2059
2060                         Assert.That (lookup.Contains (5), Is.True);
2061                         e = lookup [5].GetEnumerator ();
2062                         e.MoveNext (); Assert.That (e.Current, Is.EqualTo ("EAGLE"));
2063                         e.MoveNext (); Assert.That (e.Current, Is.EqualTo ("CAMEL"));
2064                         Assert.That (e.MoveNext (), Is.False);
2065                 }
2066
2067                 [Test]
2068                 [ExpectedException (typeof (ArgumentNullException))]
2069                 public void Union_SecondArg_PassNullAsArgument_ThrowsArgumentNullException ()
2070                 {
2071                         Read<object> ().Union (null);
2072                 }
2073
2074                 [Test]
2075                 public void Union_SecondArg_ValidIntArguments_NoDuplicatesAndInSourceOrder ()
2076                 {
2077                         var source = Read (5, 3, 9, 7, 5, 9, 3, 7);
2078                         var argument = Read (8, 3, 6, 4, 4, 9, 1, 0);
2079                         source.Union (argument).AssertEquals (5, 3, 9, 7, 8, 6, 4, 1, 0);
2080                 }
2081
2082                 [Test]
2083                 public void Union_SecondArgComparerArg_UpperCaseAndLowerCaseStrings_PassedComparerIsUsed ()
2084                 {
2085                         var source = Read ("A", "B", "C", "D", "E", "F");
2086                         var argument = Read ("a", "b", "c", "d", "e", "f");
2087                         source.Union (argument, StringComparer.CurrentCultureIgnoreCase).AssertEquals ("A", "B", "C", "D", "E", "F");
2088                 }
2089
2090                 [Test]
2091                 [ExpectedException (typeof (ArgumentNullException))]
2092                 public void Where_NullPredicate_ThrowsArgumentNullException ()
2093                 {
2094                         Read<object> ().Where ((Func<object, bool>) null);
2095                 }
2096
2097                 [Test]
2098                 public void Where_IntegersWithEvensPredicate_YieldsEvenIntegers ()
2099                 {
2100                         var source = Read (1, 2, 3, 4, 5);
2101                         source.Where (i => i % 2 == 0).AssertEquals (2, 4);
2102                 }
2103
2104                 [Test]
2105                 public void Where_StringsWithEvenIndexPredicate_YieldsElementsWithEvenIndex ()
2106                 {
2107                         var source = Read ("Camel", "Marlboro", "Parisienne", "Lucky Strike");
2108                         source.Where ((s, i) => i % 2 == 0).AssertEquals ("Camel", "Parisienne");
2109                 }
2110
2111                 [Test]
2112                 public void AsEnumerable_NonNullSource_ReturnsSourceReference ()
2113                 {
2114                         var source = new object [0];
2115                         Assert.That (Enumerable.AsEnumerable (source), Is.SameAs (source));
2116                 }
2117
2118                 [Test]
2119                 public void AsEnumerable_NullSource_ReturnsNull ()
2120                 {
2121                         Assert.That (Enumerable.AsEnumerable<object> (null), Is.Null);
2122                 }
2123                 
2124                 [Test]
2125                 [ExpectedException (typeof (ArgumentNullException))]
2126                 public void Zip_FirstSourceNull_ThrowsArgumentNullException ()
2127                 {
2128                         Enumerable.Zip<object, object, object> (null, new object [0], null);
2129                 }
2130                 
2131                 [Test]
2132                 [ExpectedException (typeof (ArgumentNullException))]
2133                 public void Zip_SecondSourceNull_ThrowsArgumentNullException ()
2134                 {
2135                         new object [0].Zip<object, object, object> (null, null);
2136                 }               
2137
2138                 [Test]
2139                 [ExpectedException (typeof (ArgumentNullException))]
2140                 public void Zip_ResultNull_ThrowsArgumentNullException ()
2141                 {
2142                         new object [0].Zip<object, object, object> (new object [0], null);
2143                 }               
2144
2145                 [Test]
2146                 public void Zip ()
2147                 {
2148                         var a = new [] { 'a', 'b', 'c' };
2149                         var b = new [] { 1, 2, 3 };
2150                         a.Zip (b, (f, s) => f + s.ToString ()).AssertEquals ("a1", "b2", "c3");
2151                         
2152                         a = new [] { 'a' };
2153                         b = new [] { 100, 200, 300 };
2154                         a.Zip (b, (f, s) => f + s.ToString ()).AssertEquals ("a100");
2155                 }
2156
2157
2158                 private Reader<T> Read<T> (params T [] source)
2159                 {
2160                         Debug.Assert (source != null);
2161
2162                         var reader = new Reader<T> (source);
2163
2164                         //
2165                         // If the calling test method is not expecting an exception
2166                         // then check that the source enumerator will be disposed
2167                         // by the time the test is torn.
2168                         //
2169
2170                         var disposed = false;
2171                         var enumerated = false;
2172                         reader.Disposed += delegate { disposed = true; };
2173                         reader.Enumerated += delegate { enumerated = true; };
2174                         AssertionHandler assertion = () => Assert.That (!enumerated || disposed, Is.True, "Enumerator not disposed.");
2175                         tearDownAssertions = (AssertionHandler) Delegate.Combine (tearDownAssertions, assertion);
2176
2177                         return reader;
2178                 }
2179         }
2180
2181         [Serializable]
2182         internal sealed class NonEnumerableList<T> : List<T>, IEnumerable<T> {
2183                 public NonEnumerableList () { }
2184
2185                 public NonEnumerableList (IEnumerable<T> collection) :
2186                         base (collection) { }
2187
2188                 // Re-implement GetEnumerator to be undefined.
2189
2190                 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
2191                 {
2192                         throw new NotImplementedException ();
2193                 }
2194
2195                 IEnumerator IEnumerable.GetEnumerator ()
2196                 {
2197                         return ((IEnumerable<T>) this).GetEnumerator ();
2198                 }
2199         }
2200
2201         [Serializable]
2202         internal sealed class NonEnumerableReadOnlyList<T> : ReadOnlyCollection<T>, IEnumerable<T> {
2203                 public NonEnumerableReadOnlyList () : 
2204                         this (new List<T>()) { }
2205
2206                 public NonEnumerableReadOnlyList (IList<T> collection) :
2207                         base (collection) { }
2208
2209                 // Re-implement GetEnumerator to be undefined.
2210
2211                 IEnumerator<T> IEnumerable<T>.GetEnumerator ()
2212                 {
2213                         throw new NotImplementedException ();
2214                 }
2215
2216                 IEnumerator IEnumerable.GetEnumerator()
2217                 {
2218                         return ((IEnumerable<T>) this).GetEnumerator();
2219                 }
2220         }
2221
2222     internal sealed class Reader<T> : IEnumerable<T>, IEnumerator<T>
2223     {
2224         public event EventHandler Disposed;
2225         public event EventHandler Enumerated;
2226
2227         private IEnumerable<T> source;
2228         private IEnumerator<T> cursor;
2229
2230         public Reader(IEnumerable<T> values)
2231         {
2232             Debug.Assert(values != null);
2233             source = values;
2234         }
2235
2236         private IEnumerator<T> Enumerator
2237         {
2238             get
2239             {
2240                 if (cursor == null)
2241                     GetEnumerator();
2242                 return this;
2243             }
2244         }
2245
2246         public object EOF
2247         {
2248             get { return Enumerator.MoveNext(); }
2249         }
2250
2251         public IEnumerator<T> GetEnumerator()
2252         {
2253             if (source == null) throw new Exception("A LINQ Operator called GetEnumerator() twice.");
2254             cursor = source.GetEnumerator();
2255             source = null;
2256
2257             var handler = Enumerated;
2258             if (handler != null)
2259                 handler(this, EventArgs.Empty);
2260
2261             return this;
2262         }
2263
2264         IEnumerator IEnumerable.GetEnumerator()
2265         {
2266             return GetEnumerator();
2267         }
2268
2269         public T Read()
2270         {
2271             if (!Enumerator.MoveNext())
2272                 throw new InvalidOperationException("No more elements in the source sequence.");
2273             return Enumerator.Current;
2274         }
2275
2276         void IDisposable.Dispose()
2277         {
2278             source = null;
2279             var e = cursor;
2280             cursor = null;
2281
2282             if (e != null)
2283             {
2284                 e.Dispose();
2285
2286                 var handler = Disposed;
2287                 if (handler != null)
2288                     handler(this, EventArgs.Empty);
2289             }
2290         }
2291
2292         private IEnumerator<T> GetSourceEnumerator()
2293         {
2294             if (source != null && cursor == null)
2295                 throw new InvalidOperationException(/* GetEnumerator not called yet */);
2296             if (source == null && cursor == null)
2297                 throw new ObjectDisposedException(GetType().FullName);
2298
2299             return cursor;
2300         }
2301
2302         bool IEnumerator.MoveNext()
2303         {
2304             return GetSourceEnumerator().MoveNext();
2305         }
2306
2307         void IEnumerator.Reset()
2308         {
2309             GetSourceEnumerator().Reset();
2310         }
2311
2312         T IEnumerator<T>.Current
2313         {
2314             get { return GetSourceEnumerator().Current; }
2315         }
2316
2317         object IEnumerator.Current
2318         {
2319             get { return ((IEnumerator<T>) this).Current; }
2320         }
2321     }
2322
2323     internal static class ReaderTestExtensions
2324     {
2325         public static void AssertEnded<T>(this Reader<T> reader)
2326         {
2327             Debug.Assert(reader != null);
2328
2329             Assert.That(reader.EOF, Is.False, "Too many elements in source.");
2330         }
2331
2332         public static Reader<T> AssertNext<T>(this Reader<T> reader, Constraint constraint)
2333         {
2334             Debug.Assert(reader != null);
2335             Debug.Assert(constraint != null);
2336
2337             Assert.That(reader.Read(), constraint);
2338             return reader;
2339         }
2340     }
2341
2342         internal static class Tester {
2343
2344                 public static void AssertEquals<T> (this IEnumerable<T> actuals, params T [] expectations)
2345                 {
2346                         actuals.AssertThat (a => Is.EqualTo (a), expectations);
2347                 }
2348
2349                 public static void AssertThat<T> (this IEnumerable<T> actuals, Func<T, Constraint> constrainer, params T [] expectations)
2350                 {
2351                         using (var e = actuals.GetEnumerator ()) {
2352                                 foreach (var expected in expectations) {
2353                                         e.MoveNext ();
2354                                         Assert.That (e.Current, constrainer (expected));
2355                                 }
2356
2357                                 Assert.That (e.MoveNext (), Is.False);
2358                         }
2359                 }
2360         }
2361 }