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

78 lines
2.8 KiB
Scala
Raw Normal View History

2011-04-09 01:17:58 +02:00
package sbt
package std
import Types._
import TaskExtra._
import TaskTest.tryRun
2011-11-20 05:56:30 +01:00
import TaskGen.{MaxWorkers,MaxWorkersGen}
2011-04-09 01:17:58 +02:00
import org.scalacheck._
import Prop.forAll
import Transform.taskToNode
2011-11-20 05:56:30 +01:00
import ConcurrentRestrictions.{All, completionService, limitTotal, tagged => tagged0, TagMap, unrestricted}
import java.util.concurrent.{CountDownLatch, TimeUnit}
2011-04-09 01:17:58 +02:00
object TaskSerial extends Properties("task serial")
{
val checkCycles = true
2011-11-20 05:56:30 +01:00
val Timeout = 100 // in milliseconds
2011-04-09 01:17:58 +02:00
2011-11-20 05:56:30 +01:00
def eval[T](t: Task[T]): T = tryRun(t, checkCycles, limitTotal(MaxWorkers))
2011-04-09 01:17:58 +02:00
property("Evaluates basic") = forAll { (i: Int) =>
checkResult( eval( task(i) ), i )
}
property("Evaluates Function0") = forAll { (i: Int) =>
checkResult( eval( () => i ), i )
}
2011-11-20 05:56:30 +01: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)
}
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."
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
}
object TaskTest
{
2011-11-20 05:56:30 +01:00
def run[T](root: Task[T], checkCycles: Boolean, restrictions: ConcurrentRestrictions[Task[_]]): Result[T] =
2011-04-09 01:17:58 +02:00
{
2011-11-20 05:56:30 +01:00
val (service, shutdown) = completionService[Task[_],Completed](restrictions, (x: String) => System.err.println(x))
2011-04-09 01:17:58 +02:00
2013-06-28 06:01:19 +02:00
val x = new Execute[Task](Execute.config(checkCycles), Execute.noTriggers, ExecuteProgress.empty[Task])(taskToNode(idK[Task]))
2011-04-09 01:17:58 +02:00
try { x.run(root)(service) } finally { shutdown() }
}
2011-11-20 05:56:30 +01:00
def tryRun[T](root: Task[T], checkCycles: Boolean, restrictions: ConcurrentRestrictions[Task[_]]): T =
run(root, checkCycles, restrictions) match {
2011-04-09 01:17:58 +02:00
case Value(v) => v
case Inc(i) => throw i
}
}