sbt/tasks-standard/src/test/scala/TaskSerial.scala

81 lines
3.0 KiB
Scala
Raw Normal View History

2011-04-09 01:17:58 +02:00
package sbt
package std
2015-09-11 11:00:34 +02:00
import sbt.internal.util.Types._
2014-05-07 17:52:23 +02:00
import TaskExtra._
import TaskTest.tryRun
import TaskGen.MaxWorkers
2011-04-09 01:17:58 +02:00
2014-05-07 17:52:23 +02:00
import org.scalacheck._
import Prop.forAll
import Transform.taskToNode
import ConcurrentRestrictions.{ completionService, limitTotal, tagged => tagged0, TagMap }
2011-11-20 05:56:30 +01:00
2014-05-07 17:52:23 +02:00
import java.util.concurrent.{ CountDownLatch, TimeUnit }
2011-04-09 01:17:58 +02:00
2014-05-07 17:52:23 +02:00
object TaskSerial extends Properties("task serial") {
val checkCycles = true
2016-06-18 01:12:59 +02:00
val Timeout = 100L // in milliseconds
2011-04-09 01:17:58 +02:00
2014-05-07 17:52:23 +02:00
def eval[T](t: Task[T]): T = tryRun(t, checkCycles, limitTotal(MaxWorkers))
2011-04-09 01:17:58 +02:00
2014-05-07 17:52:23 +02:00
property("Evaluates basic") = forAll { (i: Int) =>
checkResult(eval(task(i)), i)
}
2011-04-09 01:17:58 +02:00
2014-05-07 17:52:23 +02:00
property("Evaluates Function0") = forAll { (i: Int) =>
checkResult(eval(() => i), i)
}
2011-04-09 01:17:58 +02:00
// Note - This test is flaky on cpu/mem pressured machines, so we ignore it for now.
// Any test using a timeout (especially 100ms) on EC2 is guaranteed flaky.
/*
2014-05-07 17:52:23 +02:00
// verifies that all tasks get scheduled simultaneously (1-3) or do not (4)
property("Allows arbitrary task limit") = forAll(MaxWorkersGen) { (sze: Int) =>
val size = math.max(1, sze)
val halfSize = size / 2 + 1
val all =
checkArbitrary(size, tagged(_ => true), true) &&
checkArbitrary(size, unrestricted[Task[_]], true) &&
checkArbitrary(size, limitTotal[Task[_]](size), true) &&
checkArbitrary(size, limitTotal[Task[_]](halfSize), size <= halfSize)
all :| ("Size: " + size) :| ("Half size: " + halfSize)
}
*/
2011-11-20 05:56:30 +01:00
2014-05-07 17:52:23 +02:00
def checkArbitrary(size: Int, restrictions: ConcurrentRestrictions[Task[_]], shouldSucceed: Boolean) =
{
val latch = task { new CountDownLatch(size) }
def mktask = latch map { l =>
l.countDown()
l.await(Timeout, TimeUnit.MILLISECONDS)
}
val tasks = (0 until size).map(_ => mktask).toList.join.map { results =>
val success = results.forall(idFun[Boolean])
assert(success == shouldSucceed, if (shouldSucceed) unschedulableMsg else scheduledMsg)
}
checkResult(evalRestricted(tasks)(restrictions), ())
}
def unschedulableMsg = "Some tasks were unschedulable: verify this is an actual failure by extending the timeout to several seconds."
def scheduledMsg = "All tasks were unexpectedly scheduled."
2011-11-20 05:56:30 +01:00
2014-05-07 17:52:23 +02:00
def tagged(f: TagMap => Boolean) = tagged0[Task[_]](_.tags, f)
def evalRestricted[T](t: Task[T])(restrictions: ConcurrentRestrictions[Task[_]]): T =
tryRun[T](t, checkCycles, restrictions)
2011-04-09 01:17:58 +02:00
}
2014-05-07 17:52:23 +02:00
object TaskTest {
def run[T](root: Task[T], checkCycles: Boolean, restrictions: ConcurrentRestrictions[Task[_]]): Result[T] =
{
val (service, shutdown) = completionService[Task[_], Completed](restrictions, (x: String) => System.err.println(x))
val x = new Execute[Task](Execute.config(checkCycles), Execute.noTriggers, ExecuteProgress.empty[Task])(taskToNode(idK[Task]))
try { x.run(root)(service) } finally { shutdown() }
}
def tryRun[T](root: Task[T], checkCycles: Boolean, restrictions: ConcurrentRestrictions[Task[_]]): T =
run(root, checkCycles, restrictions) match {
case Value(v) => v
case Inc(i) => throw i
}
2015-09-11 11:00:34 +02:00
}