2010-04-15 Jérémie Laval <jeremie.laval@gmail.com>
[mcs.git] / class / System.Core / Test / System.Linq / ParallelEnumerableTests.cs
blob886020b23fbd503906075caf80e4543a8934c729
1 // ParallelEnumerableTests.cs
2 //
3 // Copyright (c) 2008 Jérémie "Garuma" Laval
4 //
5 // Based on Enumerable test suite by Jb Evain (jbevain@novell.com)
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 // THE SOFTWARE.
27 using System;
28 using System.Threading;
29 using System.Linq;
31 using System.Collections;
32 using System.Collections.Generic;
34 using NUnit.Framework;
36 namespace MonoTests.System.Linq.Parallel
38 [TestFixtureAttribute]
39 public class ParallelEnumerableTests
41 IEnumerable<int> baseEnumerable;
43 [SetUpAttribute]
44 public void Setup ()
46 baseEnumerable = Enumerable.Range(1, 10000);
49 void AreEquivalent (IEnumerable<int> syncEnumerable, IEnumerable<int> asyncEnumerable, int count)
51 int[] sync = Enumerable.ToArray(syncEnumerable);
52 int[] async = Enumerable.ToArray(asyncEnumerable);
54 // This is not AreEquals because ParallelQuery is non-deterministic (IParallelOrderedEnumerable is)
55 // thus the order of the initial Enumerable might not be preserved
56 CollectionAssert.AreEquivalent(sync, async, "#" + count);
59 void AreEquivalent<T> (IEnumerable<T> syncEnumerable, IEnumerable<T> asyncEnumerable, int count)
61 T[] sync = Enumerable.ToArray(syncEnumerable);
62 T[] async = Enumerable.ToArray(asyncEnumerable);
64 // This is not AreEquals because ParallelQuery is non-deterministic (IParallelOrderedEnumerable is)
65 // thus the order of the initial Enumerable might not be preserved
66 CollectionAssert.AreEquivalent(sync, async, "#" + count);
69 static void AssertAreSame<T> (IEnumerable<T> expected, IEnumerable<T> actual)
71 if (expected == null) {
72 Assert.IsNull (actual);
73 return;
76 Assert.IsNotNull (actual);
78 IEnumerator<T> ee = expected.GetEnumerator ();
79 IEnumerator<T> ea = actual.GetEnumerator ();
81 while (ee.MoveNext ()) {
82 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current + "' expected.");
83 Assert.AreEqual (ee.Current, ea.Current);
86 if (ea.MoveNext ())
87 Assert.Fail ("Unexpected element: " + ea.Current);
90 public static void AssertException<T> (Action action) where T : Exception
92 try {
93 action ();
95 catch (T) {
96 return;
98 Assert.Fail ("Expected: " + typeof (T).Name);
101 static void AssertAreSame<K, V> (K expectedKey, IEnumerable<V> expectedValues, IGrouping<K, V> actual)
103 if (expectedValues == null) {
104 Assert.IsNull (actual);
105 return;
108 Assert.IsNotNull (actual);
110 Assert.AreEqual (expectedKey, actual.Key);
112 var ee = expectedValues.GetEnumerator ();
113 var ea = actual.GetEnumerator ();
115 while (ee.MoveNext ()) {
116 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current + "' expected.");
117 Assert.AreEqual (ee.Current, ea.Current);
120 if (ea.MoveNext ())
121 Assert.Fail ("Unexpected element: " + ee.Current);
124 static void AssertAreSame<K, V> (IDictionary<K, IEnumerable<V>> expected, IEnumerable<IGrouping<K, V>> actual)
126 if (expected == null) {
127 Assert.IsNull (actual);
128 return;
131 Assert.IsNotNull (actual);
133 var ee = expected.GetEnumerator ();
134 var ea = actual.GetEnumerator ();
136 while (ee.MoveNext ()) {
137 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current.Key + "' expected.");
138 AssertAreSame (ee.Current.Key, ee.Current.Value, ea.Current);
141 if (ea.MoveNext ())
142 Assert.Fail ("Unexpected element: " + ee.Current.Key);
145 static void AssertAreSame<K, V> (IDictionary<K, IEnumerable<V>> expected, ILookup<K, V> actual)
147 if (expected == null) {
148 Assert.IsNull (actual);
149 return;
152 Assert.IsNotNull (actual);
154 var ee = expected.GetEnumerator ();
155 var ea = actual.GetEnumerator ();
157 while (ee.MoveNext ()) {
158 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current.Key + "' expected.");
159 AssertAreSame (ee.Current.Key, ee.Current.Value, ea.Current);
162 if (ea.MoveNext ())
163 Assert.Fail ("Unexpected element: " + ee.Current.Key);
166 static void AssertAreSame<K, V> (IDictionary<K, V> expected, IDictionary<K, V> actual)
168 if (expected == null) {
169 Assert.IsNull (actual);
170 return;
173 Assert.IsNotNull (actual);
175 var ee = expected.GetEnumerator ();
176 var ea = actual.GetEnumerator ();
178 while (ee.MoveNext ()) {
179 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current.Key + ", " + ee.Current.Value + "' expected.");
180 Assert.AreEqual (ee.Current.Key, ea.Current.Key);
181 Assert.AreEqual (ee.Current.Value, ea.Current.Value);
184 if (ea.MoveNext ())
185 Assert.Fail ("Unexpected element: " + ee.Current.Key + ", " + ee.Current.Value);
188 [Test]
189 public void SelectTestCase ()
191 ParallelTestHelper.Repeat (() => {
192 IEnumerable<int> sync = baseEnumerable.Select (i => i * i);
193 IEnumerable<int> async = baseEnumerable.AsParallel ().Select (i => i * i);
195 AreEquivalent(sync, async, 1);
199 [Test]
200 public void WhereTestCase ()
202 ParallelTestHelper.Repeat (() => {
203 IEnumerable<int> sync = baseEnumerable.Where(i => i % 2 == 0);
204 IEnumerable<int> async = baseEnumerable.AsParallel().Where(i => i % 2 == 0);
206 AreEquivalent(sync, async, 1);
210 [Test]
211 public void CountTestCase ()
213 ParallelTestHelper.Repeat (() => {
214 int sync = baseEnumerable.Count();
215 int async = baseEnumerable.AsParallel().Count();
217 Assert.AreEqual(sync, async, "#1");
221 [Test]
222 public void AggregateTestCase ()
224 ParallelTestHelper.Repeat (() => {
225 ParallelQuery<int> range = ParallelEnumerable.Repeat (5, 2643);
226 double average = range.Aggregate(() => new double[2],
227 (acc, elem) => { acc[0] += elem; acc[1]++; return acc; },
228 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
229 acc => acc[0] / acc[1]);
231 Assert.AreEqual(5.0, average, "#1");
235 [Test]
236 public void TestSimpleExcept ()
238 ParallelTestHelper.Repeat (() => {
239 int [] first = {0, 1, 2, 3, 4, 5};
240 int [] second = {2, 4, 6};
241 int [] result = {0, 1, 3, 5};
243 AreEquivalent (result, first.AsParallel ().Except (second.AsParallel ()), 1);
247 [Test]
248 public void TestSimpleIntersect ()
250 ParallelTestHelper.Repeat (() => {
251 int [] first = {0, 1, 2, 3, 4, 5};
252 int [] second = {2, 4, 6};
253 int [] result = {2, 4};
255 AreEquivalent (result, first.AsParallel ().Intersect (second.AsParallel ()), 1);
259 [Test]
260 public void TestSimpleUnion ()
262 ParallelTestHelper.Repeat (() => {
263 int [] first = {0, 1, 2, 3, 4, 5};
264 int [] second = {2, 4, 6};
265 int [] result = {0, 1, 2, 3, 4, 5, 6};
267 AreEquivalent (result, first.AsParallel ().Union (second.AsParallel ()), 1);
271 class Foo {}
272 class Bar : Foo {}
274 [Test]
275 public void TestCast ()
277 Bar a = new Bar ();
278 Bar b = new Bar ();
279 Bar c = new Bar ();
281 Foo [] foos = new Foo [] {a, b, c};
282 Bar [] result = new Bar [] {a, b, c};
284 AreEquivalent (result, foos.AsParallel ().Cast<Bar> (), 1);
287 [Test]
288 public void TestSkip ()
290 int [] data = {0, 1, 2, 3, 4, 5};
291 int [] result = {3, 4, 5};
293 AssertAreSame (result, data.AsParallel ().AsOrdered ().Skip (3));
296 /*[Test]
297 public void TestSkipWhile ()
299 int [] data = {0, 1, 2, 3, 4, 5};
300 int [] result = {3, 4, 5};
302 AssertAreSame (result, data.AsParallel ().AsOrdered ().SkipWhile (i => i < 3));
305 [Test]
306 public void TestTake ()
308 int [] data = {0, 1, 2, 3, 4, 5};
309 int [] result = {0, 1, 2};
311 AssertAreSame (result, data.AsParallel ().AsOrdered ().Take (3));
314 [Test]
315 public void TestTakeWhile ()
317 int [] data = {0, 1, 2, 3, 4, 5};
318 int [] result = {0, 1, 2};
320 AssertAreSame (result, data.AsParallel ().AsOrdered ().TakeWhile (i => i < 3));
323 // [Test]
324 // public void TestLast ()
325 // {
326 // int [] data = {1, 2, 3};
328 // Assert.AreEqual (3, data.AsParallel ().Last ());
329 // }
331 // [Test]
332 // public void TestLastOrDefault ()
333 // {
334 // int [] data = {};
336 // Assert.AreEqual (default (int), data.AsParallel ().LastOrDefault ());
337 // }
339 // [Test]
340 // public void TestFirst ()
341 // {
342 // int [] data = {1, 2, 3};
344 // Assert.AreEqual (1, data.AsParallel ().First ());
345 // }
347 // [Test]
348 // public void TestFirstOrDefault ()
349 // {
350 // int [] data = {};
352 // Assert.AreEqual (default (int), data.AsParallel ().FirstOrDefault ());
353 // }
355 [Test]
356 public void TestReverse ()
358 int [] data = {0, 1, 2, 3, 4};
359 int [] result = {4, 3, 2, 1, 0};
361 AssertAreSame (result, data.AsParallel ().AsOrdered ().Reverse ());
362 AssertAreSame (result, ParallelEnumerable.Range (0, 5).AsOrdered ().Reverse ());
365 [Test]
366 public void TestOrderBy ()
368 ParallelTestHelper.Repeat (() => {
369 int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
371 var q = array.AsParallel ().OrderBy ((i) => i);
372 AssertIsOrdered (q, array.Length);
376 class Baz {
377 string name;
378 int age;
380 public string Name
382 get {
383 if (string.IsNullOrEmpty (name))
384 return Age.ToString ();
386 return name + " (" + Age + ")";
390 public int Age
392 get { return age + 1; }
395 public Baz (string name, int age)
397 this.name = name;
398 this.age = age;
401 public override int GetHashCode ()
403 return this.Age ^ this.Name.GetHashCode ();
406 public override bool Equals (object obj)
408 Baz b = obj as Baz;
409 if (b == null)
410 return false;
412 return b.Age == this.Age && b.Name == this.Name;
415 public override string ToString ()
417 return this.Name;
421 static IEnumerable<Baz> CreateBazCollection ()
423 return new [] {
424 new Baz ("jb", 25),
425 new Baz ("ana", 20),
426 new Baz ("reg", 28),
427 new Baz ("ro", 25),
428 new Baz ("jb", 7),
432 [Test]
433 public void TestOrderByAgeAscendingTheByNameDescending ()
435 ParallelTestHelper.Repeat (() => {
436 var q = from b in CreateBazCollection ().AsParallel()
437 orderby b.Age ascending, b.Name descending
438 select b;
439 //var q = CreateBazCollection ().AsParallel ().OrderBy ((b) => b.Age).ThenByDescending ((b) => b.Name);
441 var expected = new [] {
442 new Baz ("jb", 7),
443 new Baz ("ana", 20),
444 new Baz ("ro", 25),
445 new Baz ("jb", 25),
446 new Baz ("reg", 28),
449 foreach (Baz b in q) {
450 Console.Write(b.Name + ", " + b.Age + "; ");
453 AssertAreSame (expected, q);
457 class Data {
458 public int ID { get; set; }
459 public string Name { get; set; }
461 public override string ToString ()
463 return ID + " " + Name;
467 IEnumerable<Data> CreateData ()
469 return new [] {
470 new Data { ID = 10, Name = "bcd" },
471 new Data { ID = 20, Name = "Abcd" },
472 new Data { ID = 20, Name = "Ab" },
473 new Data { ID = 10, Name = "Zyx" },
477 [Test]
478 public void TestOrderByIdDescendingThenByNameAscending ()
480 ParallelTestHelper.Repeat (() => {
481 var q = from d in CreateData ().AsParallel()
482 orderby d.ID descending, d.Name ascending
483 select d;
485 var list = new List<Data> (q);
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);
494 static void AssertIsOrdered (IEnumerable<int> e, int count)
496 int f = int.MinValue;
497 int c = 0;
499 foreach (int i in e) {
500 Assert.IsTrue (f <= i, string.Format ("{0} <= {1}", f, i));
501 f = i;
502 c++;
505 Assert.AreEqual (count, c);
509 [TestAttribute, Ignore]
510 public void ElementAtTestCase()
512 ParallelTestHelper.Repeat (() => {
513 Assert.AreEqual(1, baseEnumerable.ElementAt(0), "#1");
514 Assert.AreEqual(51, baseEnumerable.ElementAt(50), "#2");
515 Assert.AreEqual(489, baseEnumerable.ElementAt(488), "#3");
519 [TestAttribute, Ignore]
520 public void TakeTestCase()
522 ParallelTestHelper.Repeat (() => {
523 ParallelQuery<int> async = baseEnumerable.AsParallel().Take(2000);
524 IEnumerable<int> sync = baseEnumerable.Take(2000);
526 AreEquivalent(sync, async, 1);
528 async = baseEnumerable.AsParallel().Take(100);
529 sync = baseEnumerable.Take(100);
531 AreEquivalent(sync, async, 2);
535 [TestAttribute, Ignore]
536 public void SkipTestCase()
538 ParallelTestHelper.Repeat (() => {
539 ParallelQuery<int> async = baseEnumerable.AsParallel().AsOrdered().Skip(2000);
540 IEnumerable<int> sync = baseEnumerable.Skip(2000);
542 AreEquivalent(sync, async, 1);
544 async = baseEnumerable.AsParallel().Skip(100);
545 sync = baseEnumerable.Skip(100);
547 Assert.AreEqual(sync.Count(), async.Count(), "#2");
551 [TestAttribute, Ignore]
552 public void ZipTestCase()
554 ParallelTestHelper.Repeat (() => {
555 ParallelQuery<int> async1 = ParallelEnumerable.Range(0, 10000);
556 ParallelQuery<int> async2 = ParallelEnumerable.Repeat(1, 10000).Zip(async1, (e1, e2) => e1 + e2);
558 int[] expected = Enumerable.Range (1, 10000).ToArray ();
559 CollectionAssert.AreEquivalent(expected, Enumerable.ToArray (async2), "#1");
563 [Test]
564 public void RangeTestCase ()
566 ParallelTestHelper.Repeat (() => {
567 IEnumerable<int> sync = Enumerable.Range(1, 1000);
568 IEnumerable<int> async = ParallelEnumerable.Range(1, 1000);
570 AreEquivalent (sync, async, 1);
574 [Test]
575 public void RepeatTestCase ()
577 ParallelTestHelper.Repeat (() => {
578 IEnumerable<int> sync = Enumerable.Repeat(1, 1000);
579 IEnumerable<int> async = ParallelEnumerable.Repeat(1, 1000);
581 AreEquivalent (sync, async, 1);
585 [Test]
586 public void TestSum ()
588 int [] data = {1, 2, 3, 4};
590 Assert.AreEqual (10, data.AsParallel().Sum ());
593 [Test]
594 public void SumOnEmpty ()
596 int [] data = {};
598 Assert.AreEqual (0, data.AsParallel().Sum ());
601 [Test]
602 public void TestMax ()
604 int [] data = {1, 3, 5, 2};
606 Assert.AreEqual (5, data.AsParallel().Max ());
609 [Test]
610 public void TestMin ()
612 int [] data = {3, 5, 2, 6, 1, 7};
614 Assert.AreEqual (1, data.AsParallel().Min ());
617 [Test]
618 public void TestToListOrdered ()
620 int [] data = { 2, 3, 5 };
622 var list = data.AsParallel().AsOrdered().ToList ();
624 AssertAreSame (data, list);
625 AssertIsOrdered (list, data.Length);
627 Assert.AreEqual (typeof (List<int>), list.GetType ());
630 [Test]
631 public void TestToArrayOrdered ()
633 ICollection<int> coll = new List<int> ();
634 coll.Add (0);
635 coll.Add (1);
636 coll.Add (2);
638 int [] result = {0, 1, 2};
640 var array = coll.AsParallel().AsOrdered().ToArray ();
642 AssertAreSame (result, array);
643 AssertIsOrdered (array, result.Length);
645 Assert.AreEqual (typeof (int []), array.GetType ());
648 [Test]
649 public void TestToList ()
651 int [] data = {3, 5, 2};
653 var list = data.AsParallel().ToList ();
655 CollectionAssert.AreEquivalent (data, list);
657 Assert.AreEqual (typeof (List<int>), list.GetType ());
660 [Test]
661 public void TestToArray ()
663 ICollection<int> coll = new List<int> ();
664 coll.Add (0);
665 coll.Add (1);
666 coll.Add (2);
668 int [] result = {0, 1, 2};
670 var array = coll.AsParallel().ToArray ();
672 CollectionAssert.AreEquivalent (result, array);
674 Assert.AreEqual (typeof (int []), array.GetType ());
678 [Test]
679 public void TestAverageOnInt32 ()
681 Assert.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }).Average ());
684 [Test]
685 public void TestAverageOnInt64 ()
687 Assert.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }).Average ());
691 [Test]
692 public void AnyArgumentNullTest ()
694 string [] data = { "2", "1", "5", "3", "4" };
697 // Any<TSource> ()
698 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().Any (); });
700 // Any<TSource> (Func<TSource, bool>)
701 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().Any (x => true); });
702 AssertException<ArgumentNullException> (delegate () { data.AsParallel ().Any ((Func<string, bool>) null); });
705 [Test]
706 public void AnyTest ()
708 int [] data = { 5, 2, 3, 1, 6 };
709 int [] empty = { };
712 // Any<TSource> ()
713 Assert.IsTrue (data.AsParallel ().Any ());
714 Assert.IsFalse (empty.AsParallel ().Any ());
716 // Any<TSource> (Func<TSource, bool>)
717 Assert.IsTrue (data.AsParallel ().Any (x => x == 5));
718 Assert.IsFalse (data.AsParallel ().Any (x => x == 9));
719 Assert.IsFalse (empty.AsParallel ().Any (x => true));
723 [Test]
724 public void AllArgumentNullTest ()
726 string [] data = { "2", "1", "5", "3", "4" };
728 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().All (x => true); });
729 AssertException<ArgumentNullException> (delegate () { data.AsParallel ().All ((Func<string, bool>) null); });
732 [Test]
733 public void AllTest ()
735 int [] data = { 5, 2, 3, 1, 6 };
736 int [] empty = { };
738 Assert.IsTrue (data.AsParallel ().All (x => true));
739 Assert.IsFalse (data.AsParallel ().All (x => x != 1));
740 Assert.IsTrue (empty.AsParallel ().All (x => false));