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
28 using System
.Threading
;
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
;
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
);
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
);
87 Assert
.Fail ("Unexpected element: " + ea
.Current
);
90 public static void AssertException
<T
> (Action action
) where T
: Exception
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
185 Assert
.Fail ("Unexpected element: " + ee
.Current
.Key
+ ", " + ee
.Current
.Value
);
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);
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);
211 public void CountTestCase ()
213 ParallelTestHelper
.Repeat (() => {
214 int sync
= baseEnumerable
.Count();
215 int async = baseEnumerable
.AsParallel().Count();
217 Assert
.AreEqual(sync
, async, "#1");
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");
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);
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);
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);
275 public void TestCast ()
281 Foo
[] foos
= new Foo
[] {a, b, c}
;
282 Bar
[] result
= new Bar
[] {a, b, c}
;
284 AreEquivalent (result
, foos
.AsParallel ().Cast
<Bar
> (), 1);
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));
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));
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));
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));
324 // public void TestLast ()
326 // int [] data = {1, 2, 3};
328 // Assert.AreEqual (3, data.AsParallel ().Last ());
332 // public void TestLastOrDefault ()
336 // Assert.AreEqual (default (int), data.AsParallel ().LastOrDefault ());
340 // public void TestFirst ()
342 // int [] data = {1, 2, 3};
344 // Assert.AreEqual (1, data.AsParallel ().First ());
348 // public void TestFirstOrDefault ()
352 // Assert.AreEqual (default (int), data.AsParallel ().FirstOrDefault ());
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 ());
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
);
383 if (string.IsNullOrEmpty (name
))
384 return Age
.ToString ();
386 return name
+ " (" + Age
+ ")";
392 get { return age + 1; }
395 public Baz (string name
, int age
)
401 public override int GetHashCode ()
403 return this.Age ^
this.Name
.GetHashCode ();
406 public override bool Equals (object obj
)
412 return b
.Age
== this.Age
&& b
.Name
== this.Name
;
415 public override string ToString ()
421 static IEnumerable
<Baz
> CreateBazCollection ()
433 public void TestOrderByAgeAscendingTheByNameDescending ()
435 ParallelTestHelper
.Repeat (() => {
436 var q
= from b
in CreateBazCollection ().AsParallel()
437 orderby b
.Age
ascending, b
.Name
descending
439 //var q = CreateBazCollection ().AsParallel ().OrderBy ((b) => b.Age).ThenByDescending ((b) => b.Name);
441 var expected
= new [] {
449 foreach (Baz b
in q
) {
450 Console
.Write(b
.Name
+ ", " + b
.Age
+ "; ");
453 AssertAreSame (expected
, q
);
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 ()
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" }
,
478 public void TestOrderByIdDescendingThenByNameAscending ()
480 ParallelTestHelper
.Repeat (() => {
481 var q
= from d
in CreateData ().AsParallel()
482 orderby d
.ID
descending, d
.Name
ascending
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
;
499 foreach (int i
in e
) {
500 Assert
.IsTrue (f
<= i
, string.Format ("{0} <= {1}", f
, i
));
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");
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);
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);
586 public void TestSum ()
588 int [] data
= {1, 2, 3, 4}
;
590 Assert
.AreEqual (10, data
.AsParallel().Sum ());
594 public void SumOnEmpty ()
598 Assert
.AreEqual (0, data
.AsParallel().Sum ());
602 public void TestMax ()
604 int [] data
= {1, 3, 5, 2}
;
606 Assert
.AreEqual (5, data
.AsParallel().Max ());
610 public void TestMin ()
612 int [] data
= {3, 5, 2, 6, 1, 7}
;
614 Assert
.AreEqual (1, data
.AsParallel().Min ());
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 ());
631 public void TestToArrayOrdered ()
633 ICollection
<int> coll
= new List
<int> ();
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 ());
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 ());
661 public void TestToArray ()
663 ICollection
<int> coll
= new List
<int> ();
668 int [] result
= {0, 1, 2}
;
670 var array
= coll
.AsParallel().ToArray ();
672 CollectionAssert
.AreEquivalent (result
, array
);
674 Assert
.AreEqual (typeof (int []), array
.GetType ());
679 public void TestAverageOnInt32 ()
681 Assert
.AreEqual (23.25, (new int [] { 24, 7, 28, 34 }
).Average ());
685 public void TestAverageOnInt64 ()
687 Assert
.AreEqual (23.25, (new long [] { 24, 7, 28, 34 }
).Average ());
692 public void AnyArgumentNullTest ()
694 string [] data = { "2", "1", "5", "3", "4" };
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); });
706 public void AnyTest ()
708 int [] data
= { 5, 2, 3, 1, 6 }
;
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));
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); });
733 public void AllTest ()
735 int [] data
= { 5, 2, 3, 1, 6 }
;
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));