2010-03-12 Jb Evain <jbevain@novell.com>
[mono.git] / mcs / class / System.Core / Test / System.Linq / EnumerableTest.cs
1 //
2 // EnumerableTest.cs
3 //
4 // Author:
5 //   Jb Evain (jbevain@novell.com)
6 //
7 // (C) 2007 Novell, Inc. (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.IO;
31 using System.Collections;
32 using System.Collections.Generic;
33 using System.Linq;
34 using System.Linq.Expressions;
35
36 using NUnit.Framework;
37
38 namespace MonoTests.System.Linq {
39
40         [TestFixture]
41         public class EnumerableTest {
42
43                 [Test]
44                 public void TestSimpleExcept ()
45                 {
46                         int [] first = {0, 1, 2, 3, 4, 5};
47                         int [] second = {2, 4, 6};
48                         int [] result = {0, 1, 3, 5};
49
50                         AssertAreSame (result, first.Except (second));
51                 }
52
53                 [Test]
54                 public void TestSimpleIntersect ()
55                 {
56                         int [] first = {0, 1, 2, 3, 4, 5};
57                         int [] second = {2, 4, 6};
58                         int [] result = {2, 4};
59
60                         AssertAreSame (result, first.Intersect (second));
61                 }
62
63                 [Test]
64                 public void TestSimpleUnion ()
65                 {
66                         int [] first = {0, 1, 2, 3, 4, 5};
67                         int [] second = {2, 4, 6};
68                         int [] result = {0, 1, 2, 3, 4, 5, 6};
69
70                         AssertAreSame (result, first.Union (second));
71                 }
72
73                 class Foo {}
74                 class Bar : Foo {}
75
76                 [Test]
77                 public void TestCast ()
78                 {
79                         Bar a = new Bar ();
80                         Bar b = new Bar ();
81                         Bar c = new Bar ();
82
83                         Foo [] foos = new Foo [] {a, b, c};
84                         Bar [] result = new Bar [] {a, b, c};
85
86                         AssertAreSame (result, foos.Cast<Bar> ());
87                 }
88
89                 class Bingo : IEnumerable<int>, IEnumerable<string> {
90
91                         IEnumerator<int> IEnumerable<int>.GetEnumerator ()
92                         {
93                                 yield return 42;
94                                 yield return 12;
95                         }
96
97                         IEnumerator<string> IEnumerable<string>.GetEnumerator ()
98                         {
99                                 yield return "foo";
100                                 yield return "bar";
101                         }
102
103                         public IEnumerator GetEnumerator ()
104                         {
105                                 return (this as IEnumerable<int>).GetEnumerator ();
106                         }
107                 }
108
109                 [Test]
110                 public void TestCastToImplementedType ()
111                 {
112                         var ints = new int [] { 42, 12 };
113                         var strs = new string [] { "foo", "bar" };
114
115                         var bingo = new Bingo ();
116
117                         AssertAreSame (ints, bingo.Cast<int> ());
118                         AssertAreSame (strs, bingo.Cast<string> ());
119                 }
120
121                 [Test]
122                 public void TestLast ()
123                 {
124                         int [] data = {1, 2, 3};
125
126                         Assert.AreEqual (3, data.Last ());
127                 }
128
129                 [Test]
130                 public void TestLastOrDefault ()
131                 {
132                         int [] data = {};
133
134                         Assert.AreEqual (default (int), data.LastOrDefault ());
135                 }
136
137                 [Test]
138                 public void TestFirst ()
139                 {
140                         int [] data = {1, 2, 3};
141
142                         Assert.AreEqual (1, data.First ());
143                 }
144
145                 [Test]
146                 public void TestFirstOrDefault ()
147                 {
148                         int [] data = {};
149
150                         Assert.AreEqual (default (int), data.FirstOrDefault ());
151                 }
152
153                 [Test]
154                 public void TestSequenceEqual ()
155                 {
156                         int [] first = {0, 1, 2, 3, 4, 5};
157                         int [] second = {0, 1, 2};
158                         int [] third = {0, 1, 2, 3, 4, 5};
159
160                         Assert.IsFalse (first.SequenceEqual (second));
161                         Assert.IsTrue (first.SequenceEqual (third));
162                 }
163
164                 [Test]
165                 public void TestSkip ()
166                 {
167                         int [] data = {0, 1, 2, 3, 4, 5};
168                         int [] result = {3, 4, 5};
169
170                         AssertAreSame (result, data.Skip (3));
171                 }
172
173                 [Test]
174                 public void TestSkipWhile ()
175                 {
176                         int [] data = {0, 1, 2, 3, 4, 5};
177                         int [] result = {3, 4, 5};
178
179                         AssertAreSame (result, data.SkipWhile (i => i < 3));
180                 }
181
182                 [Test]
183                 public void TestTake ()
184                 {
185                         int [] data = {0, 1, 2, 3, 4, 5};
186                         int [] result = {0, 1, 2};
187
188                         AssertAreSame (result, data.Take (3));
189                 }
190
191                 [Test]
192                 public void TestTakeWhile ()
193                 {
194                         int [] data = {0, 1, 2, 3, 4, 5};
195                         int [] result = {0, 1, 2};
196
197                         AssertAreSame (result, data.TakeWhile (i => i < 3));
198                 }
199
200                 [Test]
201                 public void TestSelect ()
202                 {
203                         int [] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
204                         int [] result = {1, 3, 5, 7, 9};
205
206                         AssertAreSame (result, data.Where (i => i % 2 != 0));
207                 }
208
209                 [Test]
210                 public void TestReverse ()
211                 {
212                         int [] data = {0, 1, 2, 3, 4};
213                         int [] result = {4, 3, 2, 1, 0};
214
215                         AssertAreSame (result, data.Reverse ());
216                         AssertAreSame (result, Enumerable.Range (0, 5).Reverse ());
217                 }
218
219                 [Test]
220                 public void TestSum ()
221                 {
222                         int [] data = {1, 2, 3, 4};
223
224                         Assert.AreEqual (10, data.Sum ());
225                 }
226
227                 [Test]
228                 public void SumOnEmpty ()
229                 {
230                         int [] data = {};
231
232                         Assert.AreEqual (0, data.Sum ());
233                 }
234
235                 [Test]
236                 public void TestMax ()
237                 {
238                         int [] data = {1, 3, 5, 2};
239
240                         Assert.AreEqual (5, data.Max ());
241                 }
242
243                 [Test]
244                 public void TestMaxNullableInt32 ()
245                 {
246                         int? [] data = { null, null, null };
247
248                         Assert.IsNull (data.Max (x => -x));
249
250                         data = new int? [] { null, 1, 2 };
251
252                         Assert.AreEqual (-1, data.Max (x => -x));
253                 }
254
255                 [Test]
256                 public void TestMin ()
257                 {
258                         int [] data = {3, 5, 2, 6, 1, 7};
259
260                         Assert.AreEqual (1, data.Min ());
261                 }
262
263                 [Test]
264                 public void TestMinNullableInt32 ()
265                 {
266                         int? [] data = { null, null, null };
267
268                         Assert.IsNull (data.Min(x => -x));
269
270                         data = new int? [] { null, 1, 2 };
271
272                         Assert.AreEqual (-2, data.Min (x => -x));
273                 }
274
275                 [Test]
276                 public void TestMinStringEmpty ()
277                 {
278                         Assert.IsNull ((new string [0]).Min ());
279                 }
280
281                 [Test]
282                 public void TestMaxStringEmpty ()
283                 {
284                         Assert.IsNull ((new string [0]).Max ());
285                 }
286
287                 [Test]
288                 public void TestToList ()
289                 {
290                         int [] data = {3, 5, 2};
291
292                         var list = data.ToList ();
293
294                         AssertAreSame (data, list);
295
296                         Assert.AreEqual (typeof (List<int>), list.GetType ());
297                 }
298
299                 [Test]
300                 public void TestToArray ()
301                 {
302                         ICollection<int> coll = new List<int> ();
303                         coll.Add (0);
304                         coll.Add (1);
305                         coll.Add (2);
306
307                         int [] result = {0, 1, 2};
308
309                         var array = coll.ToArray ();
310
311                         AssertAreSame (result, array);
312
313                         Assert.AreEqual (typeof (int []), array.GetType ());
314                 }
315
316                 [Test]
317                 public void TestIntersect ()
318                 {
319                         int [] left = { 1, 1 }, right = { 1, 1 };
320                         int [] result = { 1 };
321
322                         AssertAreSame (result, left.Intersect (right));
323                 }
324
325                 [Test]
326                 public void TestAverageOnInt32 ()
327                 {
328                         Assert.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }).Average ());
329                 }
330
331                 [Test]
332                 public void TestAverageOnInt64 ()
333                 {
334                         Assert.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }).Average ());
335                 }
336
337                 [Test]
338                 public void TestAverageOnLongNullable ()
339                 {
340                         List<long?> list = new List<long?> ();
341                         list.Add (2);
342                         list.Add (3);
343                         Assert.AreEqual (2.5d, list.Average ());
344                 }
345
346                 [Test]
347                 public void TestRange ()
348                 {
349                         AssertAreSame (new [] {1, 2, 3, 4}, Enumerable.Range (1, 4));
350
351                         AssertAreSame (new [] {0, 1, 2, 3}, Enumerable.Range (0, 4));
352                 }
353
354                 [Test]
355                 public void TestTakeTakesProperNumberOfItems ()
356                 {
357                         var stream = new MemoryStream (new byte [] { 1, 2, 3, 4, 0 });
358
359                         Assert.AreEqual (0, stream.Position);
360
361                         foreach (byte b in AsEnumerable (stream).Take (2))
362                                 ;
363
364                         Assert.AreEqual (2, stream.Position);
365                 }
366
367                 static IEnumerable<byte> AsEnumerable (Stream stream)
368                 {
369                         byte b;
370                         while ((b = (byte) stream.ReadByte ()) >= 0)
371                                 yield return b;
372                 }
373
374                 [Test]
375                 public void TestOrderBy ()
376                 {
377                                 int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
378                                 var q = from i in array
379                                                 orderby i
380                                                 select i;
381                                 AssertIsOrdered (q);
382                 }
383
384                 class Baz {
385                         string name;
386                         int age;
387
388                         public string Name
389                         {
390                                 get {
391                                         if (string.IsNullOrEmpty (name))
392                                                 return Age.ToString ();
393
394                                         return name + " (" + Age + ")";
395                                 }
396                         }
397
398                         public int Age
399                         {
400                                 get { return age + 1; }
401                         }
402
403                         public Baz (string name, int age)
404                         {
405                                 this.name = name;
406                                 this.age = age;
407                         }
408
409                         public override int GetHashCode ()
410                         {
411                                 return this.Age ^ this.Name.GetHashCode ();
412                         }
413
414                         public override bool Equals (object obj)
415                         {
416                                 Baz b = obj as Baz;
417                                 if (b == null)
418                                         return false;
419
420                                 return b.Age == this.Age && b.Name == this.Name;
421                         }
422
423                         public override string ToString ()
424                         {
425                                 return this.Name;
426                         }
427                 }
428
429                 static IEnumerable<Baz> CreateBazCollection ()
430                 {
431                         return new [] {
432                                 new Baz ("jb", 25),
433                                 new Baz ("ana", 20),
434                                 new Baz ("reg", 28),
435                                 new Baz ("ro", 25),
436                                 new Baz ("jb", 7),
437                         };
438                 }
439
440                 [Test]
441                 public void TestOrderByAgeAscendingTheByNameDescending ()
442                 {
443                         var q = from b in CreateBazCollection ()
444                                         orderby b.Age ascending, b.Name descending
445                                         select b;
446
447                         var expected = new [] {
448                                 new Baz ("jb", 7),
449                                 new Baz ("ana", 20),
450                                 new Baz ("ro", 25),
451                                 new Baz ("jb", 25),
452                                 new Baz ("reg", 28),
453                         };
454
455                         AssertAreSame (expected, q);
456                 }
457
458                 class Data {
459                         public int ID { get; set; }
460                         public string Name { get; set; }
461
462                         public override string ToString ()
463                         {
464                                 return ID + " " + Name;
465                         }
466                 }
467
468                 IEnumerable<Data> CreateData ()
469                 {
470                         return new [] {
471                                 new Data { ID = 10, Name = "bcd" },
472                                 new Data { ID = 20, Name = "Abcd" },
473                                 new Data { ID = 20, Name = "Ab" },
474                                 new Data { ID = 10, Name = "Zyx" },
475                         };
476                 }
477
478                 [Test]
479                 public void TestOrderByIdDescendingThenByNameAscending ()
480                 {
481                         var q = from d in CreateData ()
482                                         orderby d.ID descending, d.Name ascending
483                                         select d;
484
485                         var list = new List<Data> (q);
486
487                         Assert.AreEqual ("Ab", list [0].Name);
488                         Assert.AreEqual ("Abcd", list [1].Name);
489                         Assert.AreEqual ("bcd", list [2].Name);
490                         Assert.AreEqual ("Zyx", list [3].Name);
491                 }
492
493                 static void AssertIsOrdered (IEnumerable<int> e)
494                 {
495                                 int f = int.MinValue;
496                                 foreach(int i in e) {
497                                                 Assert.IsTrue (f <= i);
498                                                 f = i;
499                                 }
500                 }
501
502                 static void AssertAreSame<T> (IEnumerable<T> expected, IEnumerable<T> actual)
503                 {
504                         if (expected == null) {
505                                 Assert.IsNull (actual);
506                                 return;
507                         }
508
509                         Assert.IsNotNull (actual);
510
511                         IEnumerator<T> ee = expected.GetEnumerator ();
512                         IEnumerator<T> ea = actual.GetEnumerator ();
513
514                         while (ee.MoveNext ()) {
515                                 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current + "' expected.");
516                                 Assert.AreEqual (ee.Current, ea.Current);
517                         }
518
519                         if (ea.MoveNext ())
520                                 Assert.Fail ("Unexpected element: " + ea.Current);
521                 }
522         }
523 }