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 TestSkipWhile ()
301 int [] data = {0, 1, 2, 3, 4, 5};
302 int [] result = {3, 4, 5};
304 AssertAreSame (result, data.AsParallel ().AsOrdered ().SkipWhile (i => i < 3));
308 public void TestTake ()
310 int [] data = {0, 1, 2, 3, 4, 5};
311 int [] result = {0, 1, 2};
313 AssertAreSame (result, data.AsParallel ().AsOrdered ().Take (3));
317 public void TestTakeWhile ()
319 int [] data = {0, 1, 2, 3, 4, 5};
320 int [] result = {0, 1, 2};
322 AssertAreSame (result, data.AsParallel ().AsOrdered ().TakeWhile (i => i < 3));
326 // public void TestLast ()
328 // int [] data = {1, 2, 3};
330 // Assert.AreEqual (3, data.AsParallel ().Last ());
334 // public void TestLastOrDefault ()
338 // Assert.AreEqual (default (int), data.AsParallel ().LastOrDefault ());
342 // public void TestFirst ()
344 // int [] data = {1, 2, 3};
346 // Assert.AreEqual (1, data.AsParallel ().First ());
350 // public void TestFirstOrDefault ()
354 // Assert.AreEqual (default (int), data.AsParallel ().FirstOrDefault ());
358 public void TestReverse ()
360 int [] data = {0, 1, 2, 3, 4};
361 int [] result = {4, 3, 2, 1, 0};
363 AssertAreSame (result, data.AsParallel ().AsOrdered ().Reverse ());
364 AssertAreSame (result, ParallelEnumerable.Range (0, 5).AsOrdered ().Reverse ());
368 public void TestOrderBy ()
370 ParallelTestHelper.Repeat (() => {
371 int [] array = { 14, 53, 3, 9, 11, 14, 5, 32, 2 };
373 var q = array.AsParallel ().OrderBy ((i) => i);
374 AssertIsOrdered (q, array.Length);
385 if (string.IsNullOrEmpty (name))
386 return Age.ToString ();
388 return name + " (" + Age + ")";
394 get { return age + 1; }
397 public Baz (string name, int age)
403 public override int GetHashCode ()
405 return this.Age ^ this.Name.GetHashCode ();
408 public override bool Equals (object obj)
414 return b.Age == this.Age && b.Name == this.Name;
417 public override string ToString ()
423 static IEnumerable<Baz> CreateBazCollection ()
435 public void TestOrderByAgeAscendingTheByNameDescending ()
437 ParallelTestHelper.Repeat (() => {
438 var q = from b in CreateBazCollection ().AsParallel()
439 orderby b.Age ascending, b.Name descending
441 //var q = CreateBazCollection ().AsParallel ().OrderBy ((b) => b.Age).ThenByDescending ((b) => b.Name);
443 var expected = new [] {
451 foreach (Baz b in q) {
452 Console.Write(b.Name + ", " + b.Age + "; ");
455 AssertAreSame (expected, q);
460 public int ID { get; set; }
461 public string Name { get; set; }
463 public override string ToString ()
465 return ID + " " + Name;
469 IEnumerable<Data> CreateData ()
472 new Data { ID = 10, Name = "bcd" },
473 new Data { ID = 20, Name = "Abcd" },
474 new Data { ID = 20, Name = "Ab" },
475 new Data { ID = 10, Name = "Zyx" },
480 public void TestOrderByIdDescendingThenByNameAscending ()
482 ParallelTestHelper.Repeat (() => {
483 var q = from d in CreateData ().AsParallel()
484 orderby d.ID descending, d.Name ascending
487 var list = new List<Data> (q);
489 Assert.AreEqual ("Ab", list [0].Name);
490 Assert.AreEqual ("Abcd", list [1].Name);
491 Assert.AreEqual ("bcd", list [2].Name);
492 Assert.AreEqual ("Zyx", list [3].Name);
496 static void AssertIsOrdered (IEnumerable<int> e, int count)
498 int f = int.MinValue;
501 foreach (int i in e) {
502 Assert.IsTrue (f <= i, string.Format ("{0} <= {1}", f, i));
507 Assert.AreEqual (count, c);
511 [TestAttribute, Ignore]
512 public void ElementAtTestCase()
514 ParallelTestHelper.Repeat (() => {
515 Assert.AreEqual(1, baseEnumerable.ElementAt(0), "#1");
516 Assert.AreEqual(51, baseEnumerable.ElementAt(50), "#2");
517 Assert.AreEqual(489, baseEnumerable.ElementAt(488), "#3");
521 [TestAttribute, Ignore]
522 public void TakeTestCase()
524 ParallelTestHelper.Repeat (() => {
525 ParallelQuery<int> async = baseEnumerable.AsParallel().Take(2000);
526 IEnumerable<int> sync = baseEnumerable.Take(2000);
528 AreEquivalent(sync, async, 1);
530 async = baseEnumerable.AsParallel().Take(100);
531 sync = baseEnumerable.Take(100);
533 AreEquivalent(sync, async, 2);
537 [TestAttribute, Ignore]
538 public void SkipTestCase()
540 ParallelTestHelper.Repeat (() => {
541 ParallelQuery<int> async = baseEnumerable.AsParallel().AsOrdered().Skip(2000);
542 IEnumerable<int> sync = baseEnumerable.Skip(2000);
544 AreEquivalent(sync, async, 1);
546 async = baseEnumerable.AsParallel().Skip(100);
547 sync = baseEnumerable.Skip(100);
549 Assert.AreEqual(sync.Count(), async.Count(), "#2");
553 [TestAttribute, Ignore]
554 public void ZipTestCase()
556 ParallelTestHelper.Repeat (() => {
557 ParallelQuery<int> async1 = ParallelEnumerable.Range(0, 10000);
558 ParallelQuery<int> async2 = ParallelEnumerable.Repeat(1, 10000).Zip(async1, (e1, e2) => e1 + e2);
560 int[] expected = Enumerable.Range (1, 10000).ToArray ();
561 CollectionAssert.AreEquivalent(expected, Enumerable.ToArray (async2), "#1");
566 public void RangeTestCase ()
568 ParallelTestHelper.Repeat (() => {
569 IEnumerable<int> sync = Enumerable.Range(1, 1000);
570 IEnumerable<int> async = ParallelEnumerable.Range(1, 1000);
572 AreEquivalent (sync, async, 1);
577 public void RepeatTestCase ()
579 ParallelTestHelper.Repeat (() => {
580 IEnumerable<int> sync = Enumerable.Repeat(1, 1000);
581 IEnumerable<int> async = ParallelEnumerable.Repeat(1, 1000);
583 AreEquivalent (sync, async, 1);
588 public void TestSum ()
590 int [] data = {1, 2, 3, 4};
592 Assert.AreEqual (10, data.AsParallel().Sum ());
596 public void SumOnEmpty ()
600 Assert.AreEqual (0, data.AsParallel().Sum ());
604 public void TestMax ()
606 int [] data = {1, 3, 5, 2};
608 Assert.AreEqual (5, data.AsParallel().Max ());
612 public void TestMin ()
614 int [] data = {3, 5, 2, 6, 1, 7};
616 Assert.AreEqual (1, data.AsParallel().Min ());
620 public void TestToListOrdered ()
622 int [] data = { 2, 3, 5 };
624 var list = data.AsParallel().AsOrdered().ToList ();
626 AssertAreSame (data, list);
627 AssertIsOrdered (list, data.Length);
629 Assert.AreEqual (typeof (List<int>), list.GetType ());
633 public void TestToArrayOrdered ()
635 ICollection<int> coll = new List<int> ();
640 int [] result = {0, 1, 2};
642 var array = coll.AsParallel().AsOrdered().ToArray ();
644 AssertAreSame (result, array);
645 AssertIsOrdered (array, result.Length);
647 Assert.AreEqual (typeof (int []), array.GetType ());
651 public void TestToList ()
653 int [] data = {3, 5, 2};
655 var list = data.AsParallel().ToList ();
657 CollectionAssert.AreEquivalent (data, list);
659 Assert.AreEqual (typeof (List<int>), list.GetType ());
663 public void TestToArray ()
665 ICollection<int> coll = new List<int> ();
670 int [] result = {0, 1, 2};
672 var array = coll.AsParallel().ToArray ();
674 CollectionAssert.AreEquivalent (result, array);
676 Assert.AreEqual (typeof (int []), array.GetType ());
681 public void TestAverageOnInt32 ()
683 Assert.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }).Average ());
687 public void TestAverageOnInt64 ()
689 Assert.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }).Average ());
694 public void AnyArgumentNullTest ()
696 string [] data = { "2", "1", "5", "3", "4" };
700 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().Any (); });
702 // Any<TSource> (Func<TSource, bool>)
703 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().Any (x => true); });
704 AssertException<ArgumentNullException> (delegate () { data.AsParallel ().Any ((Func<string, bool>) null); });
708 public void AnyTest ()
710 int [] data = { 5, 2, 3, 1, 6 };
715 Assert.IsTrue (data.AsParallel ().Any ());
716 Assert.IsFalse (empty.AsParallel ().Any ());
718 // Any<TSource> (Func<TSource, bool>)
719 Assert.IsTrue (data.AsParallel ().Any (x => x == 5));
720 Assert.IsFalse (data.AsParallel ().Any (x => x == 9));
721 Assert.IsFalse (empty.AsParallel ().Any (x => true));
726 public void AllArgumentNullTest ()
728 string [] data = { "2", "1", "5", "3", "4" };
730 AssertException<ArgumentNullException> (delegate () { ((IEnumerable<string>) null).AsParallel ().All (x => true); });
731 AssertException<ArgumentNullException> (delegate () { data.AsParallel ().All ((Func<string, bool>) null); });
735 public void AllTest ()
737 int [] data = { 5, 2, 3, 1, 6 };
740 Assert.IsTrue (data.AsParallel ().All (x => true));
741 Assert.IsFalse (data.AsParallel ().All (x => x != 1));
742 Assert.IsTrue (empty.AsParallel ().All (x => false));