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