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