Skip to content

Commit 10013dd

Browse files
committed
Enable tests for ParArray, ParVector and ParRange
Parallel collections are not anymore comparable with sequential collections. Tests systematically replace `==` with `sameElements`.
1 parent 42488de commit 10013dd

File tree

8 files changed

+88
-94
lines changed

8 files changed

+88
-94
lines changed

core/src/main/scala/scala/collection/parallel/ParIterableLike.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,7 @@ self =>
792792
tasksupport.executeAndWaitResult(new CopyToArray(start, len, xs, splitter))
793793
}
794794

795+
// FIXME Push down to `ParSeq`?
795796
def sameElements[U >: T](that: ParIterable[U]) = seq.iterator.sameElements(that)
796797

797798
def zip[U >: T, S](that: ParIterable[S]): CC[(U, S)] = {

scalacheck/src/test/scala/IntOperators.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ trait IntOperators extends Operators[Int] {
5050
(Int.MinValue, math.max(_, _)),
5151
(Int.MaxValue, math.min(_, _))
5252
)
53-
def addAllTraversables = List(
53+
def addAllIterables = List(
5454
List[Int](),
5555
List(1),
5656
List(1, 2),

scalacheck/src/test/scala/Operators.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ trait Operators[T] {
88
def findPredicates: List[T => Boolean]
99
def mapFunctions: List[T => T]
1010
def partialMapFunctions: List[PartialFunction[T, T]]
11-
def flatMapFunctions: List[T => Traversable[T]]
11+
def flatMapFunctions: List[T => Iterable[T]]
1212
def filterPredicates: List[T => Boolean]
1313
def filterNotPredicates: List[T => Boolean]
1414
def partitionPredicates: List[T => Boolean]
1515
def takeWhilePredicates: List[T => Boolean]
1616
def dropWhilePredicates: List[T => Boolean]
1717
def spanPredicates: List[T => Boolean]
1818
def foldArguments: List[(T, (T, T) => T)]
19-
def addAllTraversables: List[Traversable[T]]
19+
def addAllIterables: List[Iterable[T]]
2020
def newArray(sz: Int): Array[T]
2121
def groupByFunctions: List[T => T]
2222
}

scalacheck/src/test/scala/ParallelArrayCheck.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ abstract class ParallelArrayCheck[T](tp: String) extends ParallelSeqCheck[T]("Pa
4343

4444
property("array mappings must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) =>
4545
val results = for ((f, ind) <- mapFunctions.zipWithIndex)
46-
yield ("op index: " + ind) |: t.map(f) == coll.map(f)
46+
yield ("op index: " + ind) |: t.map(f).sameElements(coll.map(f))
4747
results.reduceLeft(_ && _)
4848
}
4949

scalacheck/src/test/scala/ParallelIterableCheck.scala

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import org.scalacheck.Gen._
66
import org.scalacheck.Prop._
77
import org.scalacheck.Properties
88

9+
import scala.language.higherKinds
910
import scala.collection._
1011
import scala.collection.parallel._
1112

@@ -14,7 +15,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
1415

1516
def values: Seq[Gen[T]]
1617
def ofSize(vals: Seq[Gen[T]], sz: Int): Iterable[T]
17-
def fromTraversable(t: Traversable[T]): CollType
18+
def fromIterable(t: Iterable[T]): CollType
1819
def isCheckingViews: Boolean
1920
def hasStrictOrder: Boolean
2021

@@ -30,7 +31,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
3031
)
3132

3233
// used to check if constructed collection is valid
33-
def checkDataStructureInvariants(orig: Traversable[T], cf: AnyRef) = {
34+
def checkDataStructureInvariants(orig: Iterable[T], cf: AnyRef) = {
3435
// can be overridden in subclasses
3536
true
3637
}
@@ -49,21 +50,21 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
4950

5051
def sampleValue: T = sample(values(rnd.nextInt(values.length)))
5152

52-
def collectionPairs = for (inst <- instances(values)) yield (inst, fromTraversable(inst))
53+
def collectionPairs = for (inst <- instances(values)) yield (inst, fromIterable(inst))
5354

5455
def collectionPairsWithLengths = for (inst <- instances(values); s <- choose(0, inst.size))
55-
yield (inst, fromTraversable(inst), s)
56+
yield (inst, fromIterable(inst), s)
5657

5758
def collectionPairsWith2Indices = for (
5859
inst <- instances(values);
5960
f <- choose(0, inst.size);
6061
s <- choose(0, inst.size))
61-
yield (inst, fromTraversable(inst), f, s)
62+
yield (inst, fromIterable(inst), f, s)
6263

6364
def collectionTriplets = for (inst <- instances(values);
6465
updStart <- choose(0, inst.size); howMany <- choose(0, inst.size)) yield {
6566
val modif = inst.toSeq.patch(updStart, inst.toSeq, howMany)
66-
(inst, fromTraversable(inst), modif)
67+
(inst, fromIterable(inst), modif)
6768
}
6869

6970
// def areEqual(t1: GenTraversable[T], t2: GenTraversable[T]) = if (hasStrictOrder) {
@@ -84,7 +85,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
8485
println(coll.tasksupport.debugMessages.mkString("\n"))
8586
}
8687

87-
def printComparison(t: Traversable[_], coll: ParIterable[_], tf: Traversable[_], cf: ParIterable[_], ind: Int): Unit = {
88+
def printComparison(t: Iterable[_], coll: ParIterable[_], tf: Iterable[_], cf: ParIterable[_], ind: Int): Unit = {
8889
printDebugInfo(coll)
8990
println("Operator: " + ind)
9091
println("sz: " + t.size)
@@ -100,8 +101,8 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
100101
println("size: " + cf.size)
101102
println(cf)
102103
println
103-
// println("tf == cf - " + (tf == cf))
104-
// println("cf == tf - " + (cf == tf))
104+
println("tf sameElements cf - " + (tf.iterator sameElements cf))
105+
println("cf sameElements tf - " + (cf.iterator sameElements tf))
105106
}
106107

107108
property("reductions must be equal for assoc. operators") = forAllNoShrink(collectionPairs) { case (t, coll) =>
@@ -241,15 +242,15 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
241242

242243
if (!isCheckingViews) property("partitions must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) =>
243244
(for ((p, ind) <- partitionPredicates.zipWithIndex) yield {
244-
val tpart = t.partition(p)
245-
val cpart = coll.partition(p)
246-
if (tpart != cpart) {
245+
val tpart @ (tpart1, tpart2) = t.partition(p)
246+
val cpart @ (cpart1, cpart2) = coll.partition(p)
247+
if (!tpart1.iterator.sameElements(cpart1) || !tpart2.iterator.sameElements(cpart2)) {
247248
println("from: " + t)
248249
println("and: " + coll)
249250
println(cpart)
250251
println(tpart)
251252
}
252-
("op index: " + ind) |: tpart == cpart
253+
("op index: " + ind) |: (tpart1.iterator.sameElements(cpart1) && tpart2.iterator.sameElements(cpart2))
253254
}).reduceLeft(_ && _)
254255
}
255256

@@ -286,16 +287,16 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
286287
// }
287288

288289
if (hasStrictOrder) property("splits must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (t, coll, n) =>
289-
val tspl = t.splitAt(n)
290-
val cspl = coll.splitAt(n)
291-
if (tspl != cspl) {
290+
val tspl @ (tspl1, tspl2) = t.splitAt(n)
291+
val cspl @ (cspl1, cspl2) = coll.splitAt(n)
292+
if (!tspl1.iterator.sameElements(cspl1) || !tspl2.iterator.sameElements(cspl2)) {
292293
println("at: " + n)
293294
println("from: " + t)
294295
println("and: " + coll)
295296
println(tspl)
296297
println(cspl)
297298
}
298-
("splitAt " + n) |: tspl == cspl
299+
("splitAt " + n) |: (tspl1.iterator.sameElements(cspl1) && tspl2.iterator.sameElements(cspl2))
299300
}
300301

301302
// if (hasStrictOrder) property("takeWhiles must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) =>
@@ -315,9 +316,9 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
315316

316317
if (hasStrictOrder) property("spans must be equal") = forAllNoShrink(collectionPairs) { case (t, coll) =>
317318
(for ((pred, ind) <- spanPredicates.zipWithIndex) yield {
318-
val tsp = t.span(pred)
319-
val csp = coll.span(pred)
320-
if (tsp != csp) {
319+
val tsp @ (tsp1, tsp2) = t.span(pred)
320+
val csp @ (csp1, csp2) = coll.span(pred)
321+
if (!tsp1.iterator.sameElements(csp1) || !tsp2.iterator.sameElements(csp2)) {
321322
println("from: " + t)
322323
println("and: " + coll)
323324
println("span with predicate " + ind)
@@ -327,7 +328,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col
327328
println(coll.span(pred))
328329
println("---------------------------------")
329330
}
330-
("operator " + ind) |: tsp == csp
331+
("operator " + ind) |: (tsp1.iterator.sameElements(csp1) && tsp2.iterator.sameElements(csp2))
331332
}).reduceLeft(_ && _)
332333
}
333334

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,48 @@
1-
//package scala.collection.parallel
2-
//package immutable
3-
//
4-
//import org.scalacheck._
5-
//import org.scalacheck.Gen
6-
//import org.scalacheck.Gen._
7-
//import org.scalacheck.Prop._
8-
//import org.scalacheck.Properties
9-
//import org.scalacheck.Arbitrary._
10-
//
11-
//import scala.collection._
12-
//import scala.collection.parallel.ops._
13-
//
14-
//abstract class ParallelRangeCheck(val tasksupport: TaskSupport) extends ParallelSeqCheck[Int]("ParallelRange[Int]") with ops.IntSeqOperators {
15-
// // ForkJoinTasks.defaultForkJoinPool.setMaximumPoolSize(Runtime.getRuntime.availableProcessors * 2)
16-
// // ForkJoinTasks.defaultForkJoinPool.setParallelism(Runtime.getRuntime.availableProcessors * 2)
17-
//
18-
// type CollType = collection.parallel.ParSeq[Int]
19-
//
20-
// def hasStrictOrder = true
21-
//
22-
// def isCheckingViews = false
23-
//
24-
// def ofSize(vals: Seq[Gen[Int]], sz: Int) = throw new UnsupportedOperationException
25-
//
26-
// override def instances(vals: Seq[Gen[Int]]): Gen[Seq[Int]] = sized { start =>
27-
// sized { end =>
28-
// sized { step =>
29-
// Range(start, end, if (step != 0) step else 1)
30-
// }
31-
// }
32-
// }
33-
//
34-
// def fromSeq(a: Seq[Int]) = a match {
35-
// case r: Range =>
36-
// val pr = ParRange(r.start, r.end, r.step, false)
37-
// pr.tasksupport = tasksupport
38-
// pr
39-
// case _ =>
40-
// val pa = new parallel.mutable.ParArray[Int](a.length)
41-
// pa.tasksupport = tasksupport
42-
// for (i <- 0 until a.length) pa(i) = a(i)
43-
// pa
44-
// }
45-
//
46-
// override def traversable2Seq(t: Traversable[Int]): Seq[Int] = t match {
47-
// case r: Range => r
48-
// case _ => t.toSeq
49-
// }
50-
//
51-
// def values = Seq(choose(-100, 100))
52-
//
53-
//}
1+
package scala.collection.parallel
2+
package immutable
3+
4+
import org.scalacheck._
5+
import org.scalacheck.Gen
6+
import org.scalacheck.Gen._
7+
import org.scalacheck.Prop._
8+
import org.scalacheck.Properties
9+
import org.scalacheck.Arbitrary._
10+
11+
import scala.collection._
12+
import scala.collection.parallel.ops._
13+
14+
abstract class ParallelRangeCheck(val tasksupport: TaskSupport) extends ParallelSeqCheck[Int]("ParallelRange[Int]") with ops.IntSeqOperators {
15+
// ForkJoinTasks.defaultForkJoinPool.setMaximumPoolSize(Runtime.getRuntime.availableProcessors * 2)
16+
// ForkJoinTasks.defaultForkJoinPool.setParallelism(Runtime.getRuntime.availableProcessors * 2)
17+
18+
type CollType = collection.parallel.ParSeq[Int]
19+
20+
def hasStrictOrder = true
21+
22+
def isCheckingViews = false
23+
24+
def ofSize(vals: Seq[Gen[Int]], sz: Int) = throw new UnsupportedOperationException
25+
26+
override def instances(vals: Seq[Gen[Int]]): Gen[Seq[Int]] = sized { start =>
27+
sized { end =>
28+
sized { step =>
29+
Range(start, end, if (step != 0) step else 1)
30+
}
31+
}
32+
}
33+
34+
def fromSeq(a: Seq[Int]) = a match {
35+
case r: Range =>
36+
val pr = ParRange(r.start, r.end, r.step, false)
37+
pr.tasksupport = tasksupport
38+
pr
39+
case _ =>
40+
val pa = new parallel.mutable.ParArray[Int](a.length)
41+
pa.tasksupport = tasksupport
42+
for (i <- 0 until a.length) pa(i) = a(i)
43+
pa
44+
}
45+
46+
def values = Seq(choose(-100, 100))
47+
48+
}

scalacheck/src/test/scala/ParallelSeqCheck.scala

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,7 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe
2727
)
2828

2929

30-
def fromTraversable(t: Traversable[T]) = fromSeq(traversable2Seq(t))
31-
def traversable2Seq(t: Traversable[T]): Seq[T] = {
32-
if (t.isInstanceOf[Iterable[_]]) t.asInstanceOf[Iterable[T]].iterator.toList else t.toList
33-
}
30+
def fromIterable(t: Iterable[T]) = fromSeq(t.toSeq)
3431

3532
override def collectionPairs: Gen[(Seq[T], CollType)] = for (inst <- instances(values)) yield (inst, fromSeq(inst))
3633

@@ -118,19 +115,19 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe
118115
{
119116
val sr = s.reverse
120117
val cr = coll.reverse
121-
if (sr != cr) {
118+
if (!sr.sameElements(cr)) {
122119
println("from: " + s)
123120
println("and: " + coll)
124121
println(sr)
125122
println(cr)
126123
}
127-
sr == cr
124+
sr sameElements cr
128125
}
129126
}
130127

131128
property("reverseMaps must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) =>
132129
(for ((f, ind) <- reverseMapFunctions.zipWithIndex) yield {
133-
("operator " + ind) |: s.reverseMap(f) == coll.reverseMap(f)
130+
("operator " + ind) |: s.reverseIterator.map(f).toSeq.sameElements(coll.reverseMap(f))
134131
}).reduceLeft(_ && _)
135132
}
136133

@@ -233,36 +230,36 @@ abstract class ParallelSeqCheck[T](collName: String) extends ParallelIterableChe
233230
if (s.length > 0) {
234231
val supd = s.updated(pos, s(0))
235232
val cupd = coll.updated(pos, coll(0))
236-
if (supd != cupd) {
233+
if (!supd.sameElements(cupd)) {
237234
println("from: " + s)
238235
println("and: " + coll)
239236
println(supd)
240237
println(cupd)
241238
}
242-
"from first" |: (supd == cupd)
239+
"from first" |: (supd sameElements cupd)
243240
} else "trivially" |: true
244241
}
245242

246243
property("prepends must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) =>
247-
s.length == 0 || s(0) +: s == coll(0) +: coll
244+
s.length == 0 || (s(0) +: s).sameElements(coll(0) +: coll)
248245
}
249246

250247
property("appends must be equal") = forAllNoShrink(collectionPairs) { case (s, coll) =>
251-
s.length == 0 || s :+ s(0) == coll :+ coll(0)
248+
s.length == 0 || (s :+ s(0)).sameElements(coll :+ coll(0))
252249
}
253250

254251
property("padTos must be equal") = forAllNoShrink(collectionPairsWithLengths) { case (s, coll, len) =>
255252
val someValue = sampleValue
256253
val sdoub = s.padTo(len * 2, someValue)
257254
val cdoub = coll.padTo(len * 2, someValue)
258-
if (sdoub != cdoub) {
255+
if (!sdoub.sameElements(cdoub)) {
259256
println("from: " + s)
260257
println("and: " + coll)
261258
println(sdoub)
262259
println(cdoub)
263260
}
264-
("smaller" |: s.padTo(len / 2, someValue) == coll.padTo(len / 2, someValue)) &&
265-
("bigger" |: sdoub == cdoub)
261+
("smaller" |: s.padTo(len / 2, someValue).sameElements(coll.padTo(len / 2, someValue))) &&
262+
("bigger" |: sdoub.sameElements(cdoub))
266263
}
267264

268265
property("corresponds must be equal") = forAllNoShrink(collectionPairsWithModified) { case (s, coll, modified) =>

scalacheck/src/test/scala/pc.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ package scala {
1414
// Included tests have to be abstract classes, otherwise sbt tries to instantiate them on its own and fails
1515
def includeAllTestsWith(support: TaskSupport): Unit = {
1616
// parallel arrays with default task support
17-
// include(new mutable.IntParallelArrayCheck(support) {})
17+
include(new mutable.IntParallelArrayCheck(support) {})
1818

1919
// parallel ranges
20-
// include(new immutable.ParallelRangeCheck(support) {})
20+
include(new immutable.ParallelRangeCheck(support) {})
2121

2222
// parallel immutable hash maps (tries)
2323
// include(new immutable.IntIntParallelHashMapCheck(support) {})

0 commit comments

Comments
 (0)