ccf524d29b672d6cfab0c132cd447e5e67bd859c
[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                 [Test]
90                 public void TestLast ()
91                 {
92                         int [] data = {1, 2, 3};
93
94                         Assert.AreEqual (3, data.Last ());
95                 }
96
97                 [Test]
98                 public void TestLastOrDefault ()
99                 {
100                         int [] data = {};
101
102                         Assert.AreEqual (default (int), data.LastOrDefault ());
103                 }
104
105                 [Test]
106                 public void TestFirst ()
107                 {
108                         int [] data = {1, 2, 3};
109
110                         Assert.AreEqual (1, data.First ());
111                 }
112
113                 [Test]
114                 public void TestFirstOrDefault ()
115                 {
116                         int [] data = {};
117
118                         Assert.AreEqual (default (int), data.FirstOrDefault ());
119                 }
120
121                 [Test]
122                 public void TestSequenceEqual ()
123                 {
124                         int [] first = {0, 1, 2, 3, 4, 5};
125                         int [] second = {0, 1, 2};
126                         int [] third = {0, 1, 2, 3, 4, 5};
127
128                         Assert.IsFalse (first.SequenceEqual (second));
129                         Assert.IsTrue (first.SequenceEqual (third));
130                 }
131
132                 [Test]
133                 public void TestSkip ()
134                 {
135                         int [] data = {0, 1, 2, 3, 4, 5};
136                         int [] result = {3, 4, 5};
137
138                         AssertAreSame (result, data.Skip (3));
139                 }
140
141                 [Test]
142                 public void TestSkipWhile ()
143                 {
144                         int [] data = {0, 1, 2, 3, 4, 5};
145                         int [] result = {3, 4, 5};
146
147                         AssertAreSame (result, data.SkipWhile (i => i < 3));
148                 }
149
150                 [Test]
151                 public void TestTake ()
152                 {
153                         int [] data = {0, 1, 2, 3, 4, 5};
154                         int [] result = {0, 1, 2};
155
156                         AssertAreSame (result, data.Take (3));
157                 }
158
159                 [Test]
160                 public void TestTakeWhile ()
161                 {
162                         int [] data = {0, 1, 2, 3, 4, 5};
163                         int [] result = {0, 1, 2};
164
165                         AssertAreSame (result, data.TakeWhile (i => i < 3));
166                 }
167
168                 [Test]
169                 public void TestSelect ()
170                 {
171                         int [] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
172                         int [] result = {1, 3, 5, 7, 9};
173
174                         AssertAreSame (result, data.Where (i => i % 2 != 0));
175                 }
176
177                 [Test]
178                 public void TestReverse ()
179                 {
180                         int [] data = {0, 1, 2, 3, 4};
181                         int [] result = {4, 3, 2, 1, 0};
182
183                         AssertAreSame (result, data.Reverse ());
184                         AssertAreSame (result, Enumerable.Range (0, 5).Reverse ());
185                 }
186
187                 [Test]
188                 public void TestSum ()
189                 {
190                         int [] data = {1, 2, 3, 4};
191
192                         Assert.AreEqual (10, data.Sum ());
193                 }
194
195                 [Test]
196                 public void SumOnEmpty ()
197                 {
198                         int [] data = {};
199
200                         Assert.AreEqual (0, data.Sum ());
201                 }
202
203                 [Test]
204                 public void TestMax ()
205                 {
206                         int [] data = {1, 3, 5, 2};
207
208                         Assert.AreEqual (5, data.Max ());
209                 }
210
211                 [Test]
212                 public void TestMaxNullableInt32 ()
213                 {
214                         int? [] data = { null, null, null };
215
216                         Assert.IsNull (data.Max (x => -x));
217
218                         data = new int? [] { null, 1, 2 };
219
220                         Assert.AreEqual (-1, data.Max (x => -x));
221                 }
222
223                 [Test]
224                 public void TestMin ()
225                 {
226                         int [] data = {3, 5, 2, 6, 1, 7};
227
228                         Assert.AreEqual (1, data.Min ());
229                 }
230
231                 [Test]
232                 public void TestMinNullableInt32 ()
233                 {
234                         int? [] data = { null, null, null };
235
236                         Assert.IsNull (data.Min(x => -x));
237
238                         data = new int? [] { null, 1, 2 };
239
240                         Assert.AreEqual (-2, data.Min (x => -x));
241                 }
242
243                 [Test]
244                 public void TestToList ()
245                 {
246                         int [] data = {3, 5, 2};
247
248                         var list = data.ToList ();
249
250                         AssertAreSame (data, list);
251
252                         Assert.AreEqual (typeof (List<int>), list.GetType ());
253                 }
254
255                 [Test]
256                 public void TestToArray ()
257                 {
258                         ICollection<int> coll = new List<int> ();
259                         coll.Add (0);
260                         coll.Add (1);
261                         coll.Add (2);
262
263                         int [] result = {0, 1, 2};
264
265                         var array = coll.ToArray ();
266
267                         AssertAreSame (result, array);
268
269                         Assert.AreEqual (typeof (int []), array.GetType ());
270                 }
271
272                 [Test]
273                 public void TestAverageOnInt32 ()
274                 {
275                         Assert.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }).Average ());
276                 }
277
278                 [Test]
279                 public void TestAverageOnInt64 ()
280                 {
281                         Assert.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }).Average ());
282                 }
283
284                 [Test]
285                 public void TestAverageOnLongNullable ()
286                 {
287                         List<long?> list = new List<long?> ();
288                         list.Add (2);
289                         list.Add (3);
290                         Assert.AreEqual (2.5d, list.Average ());
291                 }
292
293                 [Test]
294                 public void TestRange ()
295                 {
296                         AssertAreSame (new [] {1, 2, 3, 4}, Enumerable.Range (1, 4));
297
298                         AssertAreSame (new [] {0, 1, 2, 3}, Enumerable.Range (0, 4));
299                 }
300
301                 [Test]
302                 public void TestTakeTakesProperNumberOfItems ()
303                 {
304                         var stream = new MemoryStream (new byte [] { 1, 2, 3, 4, 0 });
305
306                         Assert.AreEqual (0, stream.Position);
307
308                         foreach (byte b in AsEnumerable (stream).Take (2))
309                                 ;
310
311                         Assert.AreEqual (2, stream.Position);
312                 }
313
314                 static IEnumerable<byte> AsEnumerable (Stream stream)
315                 {
316                         byte b;
317                         while ((b = (byte) stream.ReadByte ()) >= 0)
318                                 yield return b;
319                 }
320
321                 [Test]
322                 public void TestOrderBy ()
323                 {
324                                 int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
325                                 var q = from i in array
326                                                 orderby i
327                                                 select i;
328                                 AssertIsOrdered (q);
329                 }
330
331                 class Baz {
332                         string name;
333                         int age;
334
335                         public string Name
336                         {
337                                 get {
338                                         if (string.IsNullOrEmpty (name))
339                                                 return Age.ToString ();
340
341                                         return name + " (" + Age + ")";
342                                 }
343                         }
344
345                         public int Age
346                         {
347                                 get { return age + 1; }
348                         }
349
350                         public Baz (string name, int age)
351                         {
352                                 this.name = name;
353                                 this.age = age;
354                         }
355
356                         public override int GetHashCode ()
357                         {
358                                 return this.Age ^ this.Name.GetHashCode ();
359                         }
360
361                         public override bool Equals (object obj)
362                         {
363                                 Baz b = obj as Baz;
364                                 if (b == null)
365                                         return false;
366
367                                 return b.Age == this.Age && b.Name == this.Name;
368                         }
369
370                         public override string ToString ()
371                         {
372                                 return this.Name;
373                         }
374                 }
375
376                 static IEnumerable<Baz> CreateBazCollection ()
377                 {
378                         return new [] {
379                                 new Baz ("jb", 25),
380                                 new Baz ("ana", 20),
381                                 new Baz ("reg", 28),
382                                 new Baz ("ro", 25),
383                                 new Baz ("jb", 7),
384                         };
385                 }
386
387                 [Test]
388                 public void TestOrderByAgeAscendingTheByNameDescending ()
389                 {
390                         var q = from b in CreateBazCollection ()
391                                         orderby b.Age ascending, b.Name descending
392                                         select b;
393
394                         var expected = new [] {
395                                 new Baz ("jb", 7),
396                                 new Baz ("ana", 20),
397                                 new Baz ("ro", 25),
398                                 new Baz ("jb", 25),
399                                 new Baz ("reg", 28),
400                         };
401
402                         AssertAreSame (expected, q);
403                 }
404
405                 class Data {
406                         public int ID { get; set; }
407                         public string Name { get; set; }
408
409                         public override string ToString ()
410                         {
411                                 return ID + " " + Name;
412                         }
413                 }
414
415                 IEnumerable<Data> CreateData ()
416                 {
417                         return new [] {
418                                 new Data { ID = 10, Name = "bcd" },
419                                 new Data { ID = 20, Name = "Abcd" },
420                                 new Data { ID = 20, Name = "Ab" },
421                                 new Data { ID = 10, Name = "Zyx" },
422                         };
423                 }
424
425                 [Test]
426                 public void TestOrderByIdDescendingThenByNameAscending ()
427                 {
428                         var q = from d in CreateData ()
429                                         orderby d.ID descending, d.Name ascending
430                                         select d;
431
432                         var list = new List<Data> (q);
433
434                         Assert.AreEqual ("Ab", list [0].Name);
435                         Assert.AreEqual ("Abcd", list [1].Name);
436                         Assert.AreEqual ("bcd", list [2].Name);
437                         Assert.AreEqual ("Zyx", list [3].Name);
438                 }
439
440                 static void AssertIsOrdered (IEnumerable<int> e)
441                 {
442                                 int f = int.MinValue;
443                                 foreach(int i in e) {
444                                                 Assert.IsTrue (f <= i);
445                                                 f = i;
446                                 }
447                 }
448
449                 static void AssertAreSame<T> (IEnumerable<T> expected, IEnumerable<T> actual)
450                 {
451                         if (expected == null) {
452                                 Assert.IsNull (actual);
453                                 return;
454                         }
455
456                         Assert.IsNotNull (actual);
457
458                         IEnumerator<T> ee = expected.GetEnumerator ();
459                         IEnumerator<T> ea = actual.GetEnumerator ();
460
461                         while (ee.MoveNext ()) {
462                                 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current + "' expected.");
463                                 Assert.AreEqual (ee.Current, ea.Current);
464                         }
465
466                         if (ea.MoveNext ())
467                                 Assert.Fail ("Unexpected element: " + ea.Current);
468                 }
469         }
470 }