1 // ParallelEnumerableTests.cs
3 // Copyright (c) 2008 Jérémie "Garuma" Laval
5 // Based on Enumerable test suite by Jb Evain (jbevain@novell.com)
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
30 using System.Threading;
33 using System.Collections;
34 using System.Collections.Generic;
36 using NUnit.Framework;
38 namespace MonoTests.System.Linq
40 [TestFixtureAttribute]
41 public class ParallelEnumerableTests
43 IEnumerable<int> baseEnumerable;
48 baseEnumerable = Enumerable.Range(1, 10000);
51 void AreEquivalent (IEnumerable<int> syncEnumerable, IEnumerable<int> asyncEnumerable, int count)
53 int[] sync = Enumerable.ToArray(syncEnumerable);
54 int[] async = Enumerable.ToArray(asyncEnumerable);
56 // This is not AreEquals because ParallelQuery is non-deterministic (IParallelOrderedEnumerable is)
57 // thus the order of the initial Enumerable might not be preserved
58 CollectionAssert.AreEquivalent(sync, async, "#" + count);
61 void AreEquivalent<T> (IEnumerable<T> syncEnumerable, IEnumerable<T> asyncEnumerable, int count)
63 T[] sync = Enumerable.ToArray(syncEnumerable);
64 T[] async = Enumerable.ToArray(asyncEnumerable);
66 // This is not AreEquals because ParallelQuery is non-deterministic (IParallelOrderedEnumerable is)
67 // thus the order of the initial Enumerable might not be preserved
68 CollectionAssert.AreEquivalent(sync, async, "#" + count);
71 static void AssertAreSame<T> (IEnumerable<T> expected, IEnumerable<T> actual)
73 if (expected == null) {
74 Assert.IsNull (actual);
78 Assert.IsNotNull (actual);
80 IEnumerator<T> ee = expected.GetEnumerator ();
81 IEnumerator<T> ea = actual.GetEnumerator ();
83 while (ee.MoveNext ()) {
84 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current + "' expected.");
85 Assert.AreEqual (ee.Current, ea.Current);
89 Assert.Fail ("Unexpected element: " + ea.Current);
92 public static void AssertException<T> (Action action) where T : Exception
100 Assert.Fail ("Expected: " + typeof (T).Name);
103 static void AssertAreSame<K, V> (K expectedKey, IEnumerable<V> expectedValues, IGrouping<K, V> actual)
105 if (expectedValues == null) {
106 Assert.IsNull (actual);
110 Assert.IsNotNull (actual);
112 Assert.AreEqual (expectedKey, actual.Key);
114 var ee = expectedValues.GetEnumerator ();
115 var ea = actual.GetEnumerator ();
117 while (ee.MoveNext ()) {
118 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current + "' expected.");
119 Assert.AreEqual (ee.Current, ea.Current);
123 Assert.Fail ("Unexpected element: " + ee.Current);
126 static void AssertAreSame<K, V> (IDictionary<K, IEnumerable<V>> expected, IEnumerable<IGrouping<K, V>> actual)
128 if (expected == null) {
129 Assert.IsNull (actual);
133 Assert.IsNotNull (actual);
135 var ee = expected.GetEnumerator ();
136 var ea = actual.GetEnumerator ();
138 while (ee.MoveNext ()) {
139 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current.Key + "' expected.");
140 AssertAreSame (ee.Current.Key, ee.Current.Value, ea.Current);
144 Assert.Fail ("Unexpected element: " + ee.Current.Key);
147 static void AssertAreSame<K, V> (IDictionary<K, IEnumerable<V>> expected, ILookup<K, V> actual)
149 if (expected == null) {
150 Assert.IsNull (actual);
154 Assert.IsNotNull (actual);
156 var ee = expected.GetEnumerator ();
157 var ea = actual.GetEnumerator ();
159 while (ee.MoveNext ()) {
160 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current.Key + "' expected.");
161 AssertAreSame (ee.Current.Key, ee.Current.Value, ea.Current);
165 Assert.Fail ("Unexpected element: " + ee.Current.Key);
168 static void AssertAreSame<K, V> (IDictionary<K, V> expected, IDictionary<K, V> actual)
170 if (expected == null) {
171 Assert.IsNull (actual);
175 Assert.IsNotNull (actual);
177 var ee = expected.GetEnumerator ();
178 var ea = actual.GetEnumerator ();
180 while (ee.MoveNext ()) {
181 Assert.IsTrue (ea.MoveNext (), "'" + ee.Current.Key + ", " + ee.Current.Value + "' expected.");
182 Assert.AreEqual (ee.Current.Key, ea.Current.Key);
183 Assert.AreEqual (ee.Current.Value, ea.Current.Value);
187 Assert.Fail ("Unexpected element: " + ee.Current.Key + ", " + ee.Current.Value);
191 public void SelectTestCase ()
193 ParallelTestHelper.Repeat (() => {
194 IEnumerable<int> sync = baseEnumerable.Select (i => i * i);
195 IEnumerable<int> async = baseEnumerable.AsParallel ().Select (i => i * i);
197 AreEquivalent(sync, async, 1);
202 public void WhereTestCase ()
204 ParallelTestHelper.Repeat (() => {
205 IEnumerable<int> sync = baseEnumerable.Where(i => i % 2 == 0);
206 IEnumerable<int> async = baseEnumerable.AsParallel().Where(i => i % 2 == 0);
208 AreEquivalent(sync, async, 1);
213 public void CountTestCase ()
215 ParallelTestHelper.Repeat (() => {
216 int sync = baseEnumerable.Count();
217 int async = baseEnumerable.AsParallel().Count();
219 Assert.AreEqual(sync, async, "#1");
224 public void AggregateTestCase ()
226 ParallelTestHelper.Repeat (() => {
227 ParallelQuery<int> range = ParallelEnumerable.Repeat (5, 2643);
228 double average = range.Aggregate(() => new double[2],
229 (acc, elem) => { acc[0] += elem; acc[1]++; return acc; },
230 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
231 acc => acc[0] / acc[1]);
233 Assert.AreEqual(5.0, average, "#1");
238 public void TestSimpleExcept ()
240 ParallelTestHelper.Repeat (() => {
241 int [] first = {0, 1, 2, 3, 4, 5};
242 int [] second = {2, 4, 6};
243 int [] result = {0, 1, 3, 5};
245 AreEquivalent (result, first.AsParallel ().Except (second.AsParallel ()), 1);
250 public void TestSimpleIntersect ()
252 ParallelTestHelper.Repeat (() => {
253 int [] first = {0, 1, 2, 3, 4, 5};
254 int [] second = {2, 4, 6};
255 int [] result = {2, 4};
257 AreEquivalent (result, first.AsParallel ().Intersect (second.AsParallel ()), 1);
262 public void TestSimpleUnion ()
264 ParallelTestHelper.Repeat (() => {
265 int [] first = {0, 1, 2, 3, 4, 5};
266 int [] second = {2, 4, 6};
267 int [] result = {0, 1, 2, 3, 4, 5, 6};
269 AreEquivalent (result, first.AsParallel ().Union (second.AsParallel ()), 1);
277 public void TestCast ()
283 Foo [] foos = new Foo [] {a, b, c};
284 Bar [] result = new Bar [] {a, b, c};
286 AreEquivalent (result, foos.AsParallel ().Cast<Bar> (), 1);
290 public void TestSkip ()
292 int [] data = {0, 1, 2, 3, 4, 5};
293 int [] result = {3, 4, 5};
295 AssertAreSame (result, data.AsParallel ().AsOrdered ().Skip (3).ToArray ());
299 public void TestSkipIterating ()
301 int [] data = {0, 1, 2, 3, 4, 5};
302 int [] result = {3, 4, 5};
304 AssertAreSame (result, data.AsParallel ().AsOrdered ().Skip (3));
308 public void TestSkipWhile ()
310 int [] data = {0, 1, 2, 3, 4, 5};
311 int [] result = {3, 4, 5};
313 AssertAreSame (result, data.AsParallel ().AsOrdered ().SkipWhile (i => i < 3));
317 public void TestTake ()
319 int [] data = {0, 1, 2, 3, 4, 5};
320 int [] result = {0, 1, 2};
322 AssertAreSame (result, data.AsParallel ().AsOrdered ().Take (3));
326 public void TestTakeWhile ()
328 int [] data = {0, 1, 2, 3, 4, 5};
329 int [] result = {0, 1, 2};
331 AssertAreSame (result, data.AsParallel ().AsOrdered ().TakeWhile (i => i < 3));
335 public void TestLast ()
337 int [] data = {1, 2, 3};
339 Assert.AreEqual (3, data.AsParallel ().Last ());
343 public void TestLastOrDefault ()
347 Assert.AreEqual (default (int), data.AsParallel ().LastOrDefault ());
351 public void TestFirst ()
353 int [] data = {1, 2, 3};
355 Assert.AreEqual (1, data.AsParallel ().First ());
359 public void TestFirstOrDefault ()
363 Assert.AreEqual (default (int), data.AsParallel ().FirstOrDefault ());
367 public void TestReverse ()
369 int [] data = {0, 1, 2, 3, 4};
370 int [] result = {4, 3, 2, 1, 0};
372 AssertAreSame (result, data.AsParallel ().AsOrdered ().Reverse ());
373 AssertAreSame (result, ParallelEnumerable.Range (0, 5).AsOrdered ().Reverse ());
377 public void TestOrderBy ()
379 ParallelTestHelper.Repeat (() => {
380 int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
382 var q = array.AsParallel ().OrderBy ((i) => i);
383 AssertIsOrdered (q, array.Length);
394 if (string.IsNullOrEmpty (name))
395 return Age.ToString ();
397 return name + " (" + Age + ")";
403 get { return age + 1; }
406 public Baz (string name, int age)
412 public override int GetHashCode ()
414 return this.Age ^ this.Name.GetHashCode ();
417 public override bool Equals (object obj)
423 return b.Age == this.Age && b.Name == this.Name;
426 public override string ToString ()
432 static IEnumerable<Baz> CreateBazCollection ()
444 public void TestOrderByAgeAscendingTheByNameDescending ()
446 ParallelTestHelper.Repeat (() => {
447 var q = from b in CreateBazCollection ().AsParallel()
448 orderby b.Age ascending, b.Name descending
450 //var q = CreateBazCollection ().AsParallel ().OrderBy ((b) => b.Age).ThenByDescending ((b) => b.Name);
452 var expected = new [] {
460 foreach (Baz b in q) {
461 Console.Write(b.Name + ", " + b.Age + "; ");
464 AssertAreSame (expected, q);
469 public int ID { get; set; }
470 public string Name { get; set; }
472 public override string ToString ()
474 return ID + " " + Name;
478 IEnumerable<Data> CreateData ()
481 new Data { ID = 10, Name = "bcd" },
482 new Data { ID = 20, Name = "Abcd" },
483 new Data { ID = 20, Name = "Ab" },
484 new Data { ID = 10, Name = "Zyx" },
489 public void TestOrderByIdDescendingThenByNameAscending ()
491 ParallelTestHelper.Repeat (() => {
492 var q = from d in CreateData ().AsParallel()
493 orderby d.ID descending, d.Name ascending
496 var list = new List<Data> (q);
498 Assert.AreEqual ("Ab", list [0].Name);
499 Assert.AreEqual ("Abcd", list [1].Name);
500 Assert.AreEqual ("bcd", list [2].Name);
501 Assert.AreEqual ("Zyx", list [3].Name);
505 static void AssertIsOrdered (IEnumerable<int> e, int count)
507 int f = int.MinValue;
510 foreach (int i in e) {
511 Assert.IsTrue (f <= i, string.Format ("{0} <= {1}", f, i));
516 Assert.AreEqual (count, c);
520 [TestAttribute, Ignore]
521 public void ElementAtTestCase()
523 ParallelTestHelper.Repeat (() => {
524 Assert.AreEqual(1, baseEnumerable.ElementAt(0), "#1");
525 Assert.AreEqual(51, baseEnumerable.ElementAt(50), "#2");
526 Assert.AreEqual(489, baseEnumerable.ElementAt(488), "#3");
530 [TestAttribute, Ignore]
531 public void TakeTestCase()
533 ParallelTestHelper.Repeat (() => {
534 ParallelQuery<int> async = baseEnumerable.AsParallel().Take(2000);
535 IEnumerable<int> sync = baseEnumerable.Take(2000);
537 AreEquivalent(sync, async, 1);
539 async = baseEnumerable.AsParallel().Take(100);
540 sync = baseEnumerable.Take(100);
542 AreEquivalent(sync, async, 2);
547 public void SkipTestCase()
549 ParallelTestHelper.Repeat (() => {
550 ParallelQuery<int> async = baseEnumerable.AsParallel().AsOrdered().Skip(2000);
551 IEnumerable<int> sync = baseEnumerable.Skip(2000);
553 AreEquivalent(sync, async, 1);
555 async = baseEnumerable.AsParallel().Skip(100);
556 sync = baseEnumerable.Skip(100);
558 Assert.AreEqual(sync.Count(), async.Count(), "#2");
563 public void ZipTestCase()
565 ParallelTestHelper.Repeat (() => {
566 ParallelQuery<int> async1 = ParallelEnumerable.Range(0, 10000);
567 ParallelQuery<int> async2 = ParallelEnumerable.Repeat(1, 10000).Zip(async1, (e1, e2) => e1 + e2);
569 int[] expected = Enumerable.Range (1, 10000).ToArray ();
570 CollectionAssert.AreEquivalent(expected, Enumerable.ToArray (async2), "#1");
575 public void RangeTestCase ()
577 ParallelTestHelper.Repeat (() => {
578 IEnumerable<int> sync = Enumerable.Range(1, 1000);
579 IEnumerable<int> async = ParallelEnumerable.Range(1, 1000);
581 AreEquivalent (sync, async, 1);
586 public void RepeatTestCase ()
588 ParallelTestHelper.Repeat (() => {
589 IEnumerable<int> sync = Enumerable.Repeat(1, 1000);
590 IEnumerable<int> async = ParallelEnumerable.Repeat(1, 1000);
592 AreEquivalent (sync, async, 1);
597 public void TestSum ()
599 int [] data = {1, 2, 3, 4};
601 Assert.AreEqual (10, data.AsParallel().Sum ());
605 public void SumOnEmpty ()
609 Assert.AreEqual (0, data.AsParallel().Sum ());
613 public void TestMax ()
615 int [] data = {1, 3, 5, 2};
617 Assert.AreEqual (5, data.AsParallel().Max ());
621 public void TestMin ()
623 int [] data = {3, 5, 2, 6, 1, 7};
625 Assert.AreEqual (1, data.AsParallel().Min ());
629 public void TestToListOrdered ()
631 int [] data = { 2, 3, 5 };
633 var list = data.AsParallel().AsOrdered().ToList ();
635 AssertAreSame (data, list);
636 AssertIsOrdered (list, data.Length);
638 Assert.AreEqual (typeof (List<int>), list.GetType ());
642 public void TestToArrayOrdered ()
644 ICollection<int> coll = new List<int> ();
649 int [] result = {0, 1, 2};
651 var array = coll.AsParallel().AsOrdered().ToArray ();
653 AssertAreSame (result, array);
654 AssertIsOrdered (array, result.Length);
656 Assert.AreEqual (typeof (int []), array.GetType ());
660 public void TestToList ()
662 int [] data = {3, 5, 2};
664 var list = data.AsParallel().ToList ();
666 CollectionAssert.AreEquivalent (data, list);
668 Assert.AreEqual (typeof (List<int>), list.GetType ());
672 public void TestToArray ()
674 ICollection<int> coll = new List<int> ();
679 int [] result = {0, 1, 2};
681 var array = coll.AsParallel().ToArray ();
683 CollectionAssert.AreEquivalent (result, array);
685 Assert.AreEqual (typeof (int []), array.GetType ());
690 public void TestAverageOnInt32 ()
692 Assert.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }).Average ());
696 public void TestAverageOnInt64 ()
698 Assert.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }).Average ());
703 public void AnyArgumentNullTest ()
705 string [] data = { "2", "1", "5", "3", "4" };
709 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().Any (); });
711 // Any<TSource> (Func<TSource, bool>)
712 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().Any (x => true); });
713 AssertException<ArgumentNullException> (delegate () { data.AsParallel ().Any ((Func<string, bool>) null); });
717 public void AnyTest ()
719 int [] data = { 5, 2, 3, 1, 6 };
724 Assert.IsTrue (data.AsParallel ().Any ());
725 Assert.IsFalse (empty.AsParallel ().Any ());
727 // Any<TSource> (Func<TSource, bool>)
728 Assert.IsTrue (data.AsParallel ().Any (x => x == 5));
729 Assert.IsFalse (data.AsParallel ().Any (x => x == 9));
730 Assert.IsFalse (empty.AsParallel ().Any (x => true));
735 public void AllArgumentNullTest ()
737 string [] data = { "2", "1", "5", "3", "4" };
739 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().All (x => true); });
740 AssertException<ArgumentNullException> (delegate () { data.AsParallel ().All ((Func<string, bool>) null); });
744 public void AllTest ()
746 int [] data = { 5, 2, 3, 1, 6 };
749 Assert.IsTrue (data.AsParallel ().All (x => true));
750 Assert.IsFalse (data.AsParallel ().All (x => x != 1));
751 Assert.IsTrue (empty.AsParallel ().All (x => false));