mirror of https://github.com/sbt/sbt.git
update task tests
This commit is contained in:
parent
647a78467e
commit
4572f1b6ca
|
|
@ -0,0 +1,159 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import Types._
|
||||
import Task._
|
||||
import Execute._
|
||||
|
||||
sealed trait Task[+T]
|
||||
sealed case class Pure[+T](eval: () => T) extends Task[T]
|
||||
final case class Mapped[+T, In <: MList[Task]](in: In, f: In#Map[Result] => T) extends Task[T]
|
||||
final case class MapAll[+T, In <: MList[Task]](in: In, f: In#Map[Result]#Raw => T) extends Task[T]
|
||||
final case class FlatMapAll[+T, In <: MList[Task]](in: In, f: In#Map[Result]#Raw => Task[T]) extends Task[T]
|
||||
final case class MapFailure[+T, In <: MList[Task]](in: In, f: Seq[Incomplete] => T) extends Task[T]
|
||||
final case class FlatMapFailure[+T, In <: MList[Task]](in: In, f: Seq[Incomplete] => Task[T]) extends Task[T]
|
||||
final case class FlatMapped[+T, In <: MList[Task]](in: In, f: In#Map[Result] => Task[T]) extends Task[T]
|
||||
final case class DependsOn[+T](in: Task[T], deps: Seq[Task[_]]) extends Task[T]
|
||||
final case class Join[+T, U](in: Seq[Task[U]], f: Seq[U] => Either[Task[T], T]) extends Task[T] { type Uniform = U }
|
||||
|
||||
trait MultiInTask[M <: MList[Task]]
|
||||
{
|
||||
def flatMap[T](f: M#Map[Result]#Raw => Task[T]): Task[T]
|
||||
def flatMapR[T](f: M#Map[Result] => Task[T]): Task[T]
|
||||
def mapH[T](f: M#Map[Result]#Raw => T): Task[T]
|
||||
def mapR[T](f: M#Map[Result] => T): Task[T]
|
||||
def flatFailure[T](f: Seq[Incomplete] => Task[T]): Task[T]
|
||||
def mapFailure[T](f: Seq[Incomplete] => T): Task[T]
|
||||
}
|
||||
trait SingleInTask[S]
|
||||
{
|
||||
def flatMapR[T](f: Result[S] => Task[T]): Task[T]
|
||||
def flatMap[T](f: S => Task[T]): Task[T]
|
||||
def map[T](f: S => T): Task[T]
|
||||
def mapR[T](f: Result[S] => T): Task[T]
|
||||
def flatFailure[T](f: Incomplete => Task[T]): Task[T]
|
||||
def mapFailure[T](f: Incomplete => T): Task[T]
|
||||
def dependsOn(tasks: Task[_]*): Task[S]
|
||||
}
|
||||
trait ForkTask[S, CC[_]]
|
||||
{
|
||||
def fork[T](f: S => T): CC[Task[T]]
|
||||
}
|
||||
trait JoinTask[S, CC[_]]
|
||||
{
|
||||
def join: Task[CC[S]]
|
||||
def reduce(f: (S,S) => S): Task[S]
|
||||
}
|
||||
object Task
|
||||
{
|
||||
def pure[T](f: => T): Task[T] = toPure(f _)
|
||||
def pure[T](name: String, f: => T): Task[T] = new Pure(f _) { override def toString = name }
|
||||
implicit def toPure[T](f: () => T): Task[T] = new Pure(f)
|
||||
|
||||
implicit def toTasks[S](in: Seq[S]): Seq[Task[S]] = in.map(s => pure(s))
|
||||
implicit def toTasks[S](in: Seq[() => S]): Seq[Task[S]] = in.map(toPure)
|
||||
implicit def iterableTask[S](in: Seq[S]): ForkTask[S, Seq] = new ForkTask[S, Seq] {
|
||||
def fork[T](f: S => T): Seq[Task[T]] = in.map(x => pure(x) map f)
|
||||
}
|
||||
implicit def joinTasks[S](in: Seq[S]): JoinTask[S, Seq] = joinTasks(toTasks(in))
|
||||
implicit def joinTasks[S](in: Seq[Task[S]]): JoinTask[S, Seq] = new JoinTask[S, Seq] {
|
||||
def join: Task[Seq[S]] = new Join(in, (s: Seq[S]) => Right(s) )
|
||||
//def join[T](f: Iterable[S] => T): Task[Iterable[T]] = new MapAll( MList.fromTCList[Task](in), ml => f(ml.toList))
|
||||
//def joinR[T](f: Iterable[Result[S]] => T): Task[Iterable[Result[T]]] = new Mapped( MList.fromTCList[Task](in), ml => f(ml.toList))
|
||||
def reduce(f: (S,S) => S): Task[S] = Task.reduce(in.toIndexedSeq, f)
|
||||
}
|
||||
|
||||
|
||||
implicit def multInputTask[M <: MList[Task]](ml: M): MultiInTask[M] = new MultiInTask[M] {
|
||||
def flatMap[T](f: M#Map[Result]#Raw => Task[T]): Task[T] = new FlatMapAll(ml, f)
|
||||
def flatMapR[T](f: M#Map[Result] => Task[T]): Task[T] = new FlatMapped(ml, f)
|
||||
def mapH[T](f: M#Map[Result]#Raw => T): Task[T] = new MapAll(ml, f)
|
||||
def mapR[T](f: M#Map[Result] => T): Task[T] = new Mapped(ml, f)
|
||||
def flatFailure[T](f: Seq[Incomplete] => Task[T]): Task[T] = new FlatMapFailure(ml, f)
|
||||
def mapFailure[T](f: Seq[Incomplete] => T): Task[T] = new MapFailure(ml, f)
|
||||
}
|
||||
implicit def singleInputTask[S](in: Task[S]): SingleInTask[S] = new SingleInTask[S] {
|
||||
private val ml = in :^: MNil
|
||||
private def headM = (_: ml.Map[Result]).head
|
||||
private def headH = (_: S :+: HNil).head
|
||||
private def headS = (_: Seq[Incomplete]).head
|
||||
def flatMapR[T](f: Result[S] => Task[T]): Task[T] = new FlatMapped[T, ml.type](ml, f ∙ headM)
|
||||
def flatMap[T](f: S => Task[T]): Task[T] = new FlatMapAll[T, ml.type](ml, f ∙ headH)
|
||||
def map[T](f: S => T): Task[T] = new MapAll[T, ml.type](ml, f ∙ headH)
|
||||
def mapR[T](f: Result[S] => T): Task[T] = new Mapped[T, ml.type](ml, f ∙ headM)
|
||||
def flatFailure[T](f: Incomplete => Task[T]): Task[T] = new FlatMapFailure(ml, f ∙ headS)
|
||||
def mapFailure[T](f: Incomplete => T): Task[T] = new MapFailure(ml, f ∙ headS)
|
||||
def dependsOn(tasks: Task[_]*): Task[S] = new DependsOn(in, tasks)
|
||||
}
|
||||
|
||||
implicit val taskToNode = new (Task ~> NodeT[Task]#Apply) {
|
||||
def apply[T](t: Task[T]): Node[Task, T] = t match {
|
||||
case Pure(eval) => toNode[T, MNil](MNil, _ => Right(eval()) )
|
||||
case Mapped(in, f) => toNode[T, in.type](in, right ∙ f )
|
||||
case MapAll(in, f) => toNode[T, in.type](in, right ∙ (f compose allM) )
|
||||
case MapFailure(in, f) => toNode[T, in.type](in, right ∙ (f compose failuresM))
|
||||
case FlatMapped(in, f) => toNode[T, in.type](in, left ∙ f )
|
||||
case FlatMapAll(in, f) => toNode[T, in.type](in, left ∙ (f compose allM) )
|
||||
case FlatMapFailure(in, f) => toNode[T, in.type](in, left ∙ (f compose failuresM))
|
||||
case DependsOn(in, tasks) => join[T, Any](tasks, (_: Seq[Result[_]]) => Left(in))
|
||||
case j@ Join(in, f) => join[T, j.Uniform](in, f compose all)
|
||||
}
|
||||
}
|
||||
def join[T, D](tasks: Seq[Task[D]], f: Seq[Result[D]] => Either[Task[T], T]): Node[Task, T] = new Node[Task, T] {
|
||||
type Mixed = MNil
|
||||
val mixedIn = MNil
|
||||
type Uniform = D
|
||||
val uniformIn = tasks
|
||||
def work(mixed: MNil, uniform: Seq[Result[Uniform]]) = {
|
||||
val inc = failures(uniform)
|
||||
if(inc.isEmpty) f(uniform) else throw Incomplete(causes = inc)
|
||||
}
|
||||
}
|
||||
def toNode[T, In <: MList[Task]](in: In, f: In#Map[Result] => Either[Task[T], T]): Node[Task, T] = new Node[Task, T] {
|
||||
type Mixed = In
|
||||
val mixedIn = in
|
||||
type Uniform = Nothing
|
||||
val uniformIn = Nil
|
||||
def work(results: Mixed#Map[Result], units: Seq[Result[Uniform]]) = f(results)
|
||||
}
|
||||
def allM[In <: MList[Result]]: In => In#Raw = in =>
|
||||
{
|
||||
val incs = failuresM(in)
|
||||
if(incs.isEmpty) in.down(Result.tryValue) else throw Incomplete(causes = incs)
|
||||
}
|
||||
def all[D]: Seq[Result[D]] => Seq[D] = in =>
|
||||
{
|
||||
val incs = failures(in)
|
||||
if(incs.isEmpty) in.map(Result.tryValue.apply[D]) else throw Incomplete(causes = incs)
|
||||
}
|
||||
def failuresM[In <: MList[Result]]: In => Seq[Incomplete] = x => failures[Any](x.toList)
|
||||
def failures[A]: Seq[Result[A]] => Seq[Incomplete] = _.collect { case Inc(i) => i }
|
||||
|
||||
def run[T](root: Task[T], checkCycles: Boolean, maxWorkers: Int): Result[T] =
|
||||
{
|
||||
val (service, shutdown) = CompletionService[Task[_], Completed](maxWorkers)
|
||||
|
||||
val x = new Execute[Task](checkCycles)(taskToNode)
|
||||
try { x.run(root)(service) } finally { shutdown() }
|
||||
}
|
||||
def tryRun[T](root: Task[T], checkCycles: Boolean, maxWorkers: Int): T =
|
||||
run(root, checkCycles, maxWorkers) match {
|
||||
case Value(v) => v
|
||||
case Inc(i) => throw i
|
||||
}
|
||||
|
||||
def reduce[S](i: IndexedSeq[Task[S]], f: (S, S) => S): Task[S] =
|
||||
i match
|
||||
{
|
||||
case Seq() => error("Cannot reduce empty sequence")
|
||||
case Seq(x) => x
|
||||
case Seq(x, y) => reducePair(x, y, f)
|
||||
case z =>
|
||||
val (a, b) = i.splitAt(i.size / 2)
|
||||
reducePair( reduce(a, f), reduce(b, f), f )
|
||||
}
|
||||
def reducePair[S](a: Task[S], b: Task[S], f: (S, S) => S): Task[S] =
|
||||
(a :^: b :^: MNil) mapH { case x :+: y :+: HNil => f(x,y) }
|
||||
}
|
||||
|
|
@ -1,44 +1,49 @@
|
|||
import xsbt._
|
||||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import org.scalacheck._
|
||||
import Prop._
|
||||
import TaskGen._
|
||||
import Task._
|
||||
|
||||
object TaskRunnerSpec extends Properties("TaskRunner")
|
||||
object ExecuteSpec extends Properties("Execute")
|
||||
{
|
||||
val iGen = Arbitrary.arbInt.arbitrary
|
||||
property("evaluates simple task") = forAll(iGen, MaxWorkersGen) { (i: Int, workers: Int) =>
|
||||
("Workers: " + workers) |:
|
||||
checkResult(TaskRunner(Task(i), workers), i)
|
||||
checkResult(tryRun(pure(i), false, workers), i)
|
||||
}
|
||||
property("evaluates simple static graph") = forAll(iGen, MaxWorkersGen) { (i: Int, workers: Int) =>
|
||||
// no direct dependencies currently
|
||||
/*property("evaluates simple static graph") = forAll(iGen, MaxWorkersGen) { (i: Int, workers: Int) =>
|
||||
("Workers: " + workers) |:
|
||||
{
|
||||
def result = TaskRunner(Task(i) dependsOn(Task(false),Task("a")), workers)
|
||||
def result = tryRun(Task(i) dependsOn(pure(false),pure("a")), false, workers)
|
||||
checkResult(result, i)
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
property("evaluates simple mapped task") = forAll(iGen, MaxTasksGen, MaxWorkersGen) { (i: Int, times: Int, workers: Int) =>
|
||||
("Workers: " + workers) |: ("Value: " + i) |: ("Times: " + times) |:
|
||||
{
|
||||
def result = TaskRunner(Task(i).map(_*times), workers)
|
||||
def result = tryRun(pure(i).map(_*times), false, workers)
|
||||
checkResult(result, i*times)
|
||||
}
|
||||
}
|
||||
property("evaluates chained mapped task") = forAllNoShrink(iGen, Gen.choose(0, 1000), MaxWorkersGen) { (i: Int, times: Int, workers: Int) =>
|
||||
property("evaluates chained mapped task") = forAllNoShrink(iGen, MaxTasksGen, MaxWorkersGen) { (i: Int, times: Int, workers: Int) =>
|
||||
("Workers: " + workers) |: ("Value: " + i) |: ("Times: " + times) |:
|
||||
{
|
||||
val initial = Task(0) map(identity[Int])
|
||||
val initial = pure(0) map(identity[Int])
|
||||
def task = ( initial /: (0 until times) )( (t,ignore) => t.map(_ + i))
|
||||
checkResult(TaskRunner(task, workers), i*times)
|
||||
checkResult(tryRun(task, false, workers), i*times)
|
||||
}
|
||||
}
|
||||
|
||||
property("evaluates simple bind") = forAll(iGen, MaxTasksGen, MaxWorkersGen) { (i: Int, times: Int, workers: Int) =>
|
||||
("Workers: " + workers) |: ("Value: " + i) |: ("Times: " + times) |:
|
||||
{
|
||||
def result = TaskRunner(Task(i).bind(x => Task(x*times)), workers)
|
||||
def result = tryRun(pure(i).flatMap(x => pure(x*times)), false, workers)
|
||||
checkResult(result, i*times)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,16 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import org.scalacheck._
|
||||
import Gen.choose
|
||||
|
||||
object TaskGen
|
||||
{
|
||||
// upper bounds to make the tests finish in reasonable time
|
||||
val MaxTasks = 10000
|
||||
val MaxWorkers = 257
|
||||
val MaxTasks = 100
|
||||
val MaxWorkers = 29
|
||||
val MaxJoin = 100
|
||||
|
||||
val MaxTasksGen = choose(0, MaxTasks)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import xsbt._
|
||||
package sbt
|
||||
|
||||
import org.scalacheck._
|
||||
import Prop._
|
||||
import TaskGen._
|
||||
import Task._
|
||||
|
||||
object TaskRunnerCircularTest extends Properties("TaskRunner Circular")
|
||||
{
|
||||
|
|
@ -10,32 +11,33 @@ object TaskRunnerCircularTest extends Properties("TaskRunner Circular")
|
|||
property("Allows references to completed tasks") = forAllNoShrink(MaxTasksGen, MaxWorkersGen) { allowedReference _ }
|
||||
final def allowedReference(intermediate: Int, workers: Int) =
|
||||
{
|
||||
val top = Task(intermediate) named("top")
|
||||
val top = pure("top", intermediate)
|
||||
def iterate(task: Task[Int]): Task[Int] =
|
||||
task bind { t =>
|
||||
task flatMap { t =>
|
||||
if(t <= 0)
|
||||
top
|
||||
else
|
||||
iterate(Task(t-1) named (t-1).toString)
|
||||
iterate(pure((t-1).toString, t-1) )
|
||||
}
|
||||
try { checkResult(TaskRunner(iterate(top), workers), intermediate) }
|
||||
catch { case e: CircularDependency => ("Unexpected exception: " + e) |: false }
|
||||
try { checkResult(tryRun(iterate(top), true, workers), intermediate) }
|
||||
catch { case i: Incomplete if cyclic(i) => ("Unexpected cyclic exception: " + i) |: false }
|
||||
}
|
||||
final def checkCircularReferences(intermediate: Int, workers: Int) =
|
||||
{
|
||||
lazy val top = iterate(Task(intermediate) named"bottom", intermediate)
|
||||
lazy val top = iterate(pure("bottom", intermediate), intermediate)
|
||||
def iterate(task: Task[Int], i: Int): Task[Int] =
|
||||
{
|
||||
lazy val it: Task[Int] =
|
||||
task bind { t =>
|
||||
task flatMap { t =>
|
||||
if(t <= 0)
|
||||
top
|
||||
else
|
||||
iterate(Task(t-1) named (t-1).toString, i-1)
|
||||
} named("it_" + i)
|
||||
iterate(pure((t-1).toString, t-1), i-1)
|
||||
}
|
||||
it
|
||||
}
|
||||
try { TaskRunner(top, workers); false }
|
||||
catch { case TasksFailed(failures) => failures.exists(_.exception.isInstanceOf[CircularDependency]) }
|
||||
try { tryRun(top, true, workers); false }
|
||||
catch { case i: Incomplete => cyclic(i) }
|
||||
}
|
||||
def cyclic(i: Incomplete) = Incomplete.allExceptions(i).exists(_.isInstanceOf[Execute[Task]#CyclicException[_]])
|
||||
}
|
||||
|
|
@ -1,22 +1,22 @@
|
|||
import xsbt._
|
||||
import sbt._
|
||||
|
||||
import org.scalacheck._
|
||||
import Prop._
|
||||
import Task._
|
||||
import TaskGen._
|
||||
import Math.abs
|
||||
import math.abs
|
||||
|
||||
object TaskRunnerForkTest extends Properties("TaskRunner Fork")
|
||||
{
|
||||
property("fork m tasks and wait for all to complete") = forAll(MaxTasksGen, MaxWorkersGen) { (m: Int, workers: Int) =>
|
||||
val values = (0 until m).toList
|
||||
checkResult(TaskRunner(values.fork(f => () ).join.map(_.toList),workers), values)
|
||||
checkResult(tryRun(values.fork(f => () ).join.map(_.toList),false, workers), values)
|
||||
true
|
||||
}
|
||||
property("Fork and reduce 2") = forAll(MaxTasksGen, MaxWorkersGen) { (m: Int, workers: Int) =>
|
||||
(m > 1) ==> {
|
||||
val task = (0 to m) fork {_ * 10} reduce{_ + _}
|
||||
checkResult(TaskRunner(task, workers), 5*(m+1)*m)
|
||||
checkResult(tryRun(task, false, workers), 5*(m+1)*m)
|
||||
}
|
||||
}
|
||||
property("Double join") = forAll(MaxJoinGen, MaxJoinGen, MaxWorkersGen) { (a: Int, b: Int, workers: Int) =>
|
||||
|
|
@ -25,13 +25,13 @@ object TaskRunnerForkTest extends Properties("TaskRunner Fork")
|
|||
}
|
||||
def runDoubleJoin(a: Int, b: Int, workers: Int)
|
||||
{
|
||||
def inner(i: Int) = List.range(0, b).map(j => Task(j) named(j.toString)).join.named("Join " + i)
|
||||
TaskRunner( List.range(0,a).map(inner).join.named("Outermost join"), workers)
|
||||
def inner(i: Int) = List.range(0, b).map(j => pure(j.toString, j)).join
|
||||
tryRun( List.range(0,a).map(inner).join, false, workers)
|
||||
}
|
||||
property("fork and reduce") = forAll(TaskListGen, MaxWorkersGen) { (m: List[Int], workers: Int) =>
|
||||
(!m.isEmpty) ==> {
|
||||
val expected = m.reduceLeft(_+_)
|
||||
checkResult(TaskRunner( m.reduce(_ + _), workers), expected)
|
||||
checkResult(tryRun( m.reduce(_ + _), false, workers), expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,60 +4,22 @@
|
|||
package sbt
|
||||
|
||||
import Types._
|
||||
import Node._
|
||||
import Task._
|
||||
import Execute._
|
||||
|
||||
sealed trait Task[+T]
|
||||
sealed case class Pure[+T](eval: () => T) extends Task[T]
|
||||
sealed case class Mapped[+T, In <: MList[Task]](in: In, f: In#Map[Result] => T) extends Task[T]
|
||||
sealed case class MapAll[+T, In <: MList[Task]](in: In, f: In#Map[Result]#Raw => T) extends Task[T]
|
||||
sealed case class FlatMapAll[+T, In <: MList[Task]](in: In, f: In#Map[Result]#Raw => Task[T]) extends Task[T]
|
||||
sealed case class FlatMapped[+T, In <: MList[Task]](in: In, f: In#Map[Result] => Task[T]) extends Task[T]
|
||||
|
||||
object Task
|
||||
{
|
||||
implicit val taskToNode = new (Task ~> NodeT[Task]#Apply) {
|
||||
def apply[T](t: Task[T]): Node[Task, T] = t match {
|
||||
case Pure(eval) => toNode[T, MNil](MNil, _ => Right(eval()) )
|
||||
case Mapped(in, f) => toNode[T, in.type](in, right ∙ f )
|
||||
case MapAll(in, f) => toNode[T, in.type](in, right ∙ (f compose all) )
|
||||
case FlatMapAll(in, f) => toNode[T, in.type](in, left ∙ (f compose all) )
|
||||
case FlatMapped(in, f) => toNode[T, in.type](in, left ∙ f )
|
||||
}
|
||||
}
|
||||
def toNode[T, In <: MList[Task]](in: In, f: In#Map[Result] => Either[Task[T], T]): Node[Task, T] = new Node[Task, T] {
|
||||
type Inputs = In
|
||||
val inputs = in
|
||||
def unitDependencies = Nil
|
||||
def work(results: Results, units: UnitResults[Task]) = f(results)
|
||||
}
|
||||
|
||||
def pure[T](name: String)(f: => T): Pure[T] = new Pure(f _) { override def toString = name }
|
||||
def mapped[T, In0 <: MList[Task]](name: String)(in0: In0)(f0: In0#Map[Result] => T): Mapped[T, In0] = new Mapped(in0, f0) { override def toString = name }
|
||||
def flat[T, In0 <: MList[Task]](name: String)(in0: In0)(f0: In0#Map[Result] => Task[T]): FlatMapped[T, In0] = new FlatMapped(in0, f0) { override def toString = name }
|
||||
def mapAll[T, In0 <: MList[Task]](name: String)(in0: In0)(f0: In0#Map[Result]#Raw => T): MapAll[T, In0] = new MapAll(in0, f0) { override def toString = name }
|
||||
def flatAll[T, In0 <: MList[Task]](name: String)(in0: In0)(f0: In0#Map[Result]#Raw => Task[T]): FlatMapAll[T, In0] = new FlatMapAll(in0, f0) { override def toString = name }
|
||||
|
||||
def all[In <: MList[Result]]: In => In#Raw = in =>
|
||||
{
|
||||
val incs = in.toList.collect { case Inc(i) => i }
|
||||
if(incs.isEmpty) in.down(Result.tryValue) else throw Incomplete(causes = incs)
|
||||
}
|
||||
}
|
||||
object Test
|
||||
{
|
||||
val a = pure("a")(3)
|
||||
val b = pure[Boolean]("b")(error("test"))
|
||||
val b2 = pure("b2")(true)
|
||||
val c = pure("x")("asdf")
|
||||
val a = pure(3)
|
||||
val b = pure[Boolean](error("test"))
|
||||
val b2 = pure(true)
|
||||
val c = pure("asdf")
|
||||
val i3 = a :^: b :^: c :^: MNil
|
||||
val i32 = a :^: b2 :^: c :^: MNil
|
||||
|
||||
val fh= (_: Int :+: Boolean :+: String :+: HNil) match
|
||||
{ case aa :+: bb :+: cc :+: HNil => aa + " " + bb + " " + cc }
|
||||
val h1 = mapAll("h1")(i3)(fh)
|
||||
val h2 = mapAll("h2")(i32)(fh)
|
||||
val h1 = i3 mapH fh
|
||||
val h2 = i32 mapH fh
|
||||
|
||||
val f: i3.Map[Result] => Any = {
|
||||
case Value(aa) :^: Value(bb) :^: Value(cc) :^: MNil => aa + " " + bb + " " + cc
|
||||
|
|
@ -65,41 +27,24 @@ object Test
|
|||
val cs = x.toList.collect { case Inc(x) => x } // workaround for double definition bug
|
||||
throw Incomplete(causes = cs)
|
||||
}
|
||||
val d2 = mapped("d2")(i32)(f)
|
||||
val d2 = i32 mapR f
|
||||
val f2: i3.Map[Result] => Task[Any] = {
|
||||
case Value(aa) :^: Value(bb) :^: Value(cc) :^: MNil => new Pure(() => aa + " " + bb + " " + cc)
|
||||
case x => d3
|
||||
}
|
||||
lazy val d = flat("d")(i3)(f2)
|
||||
lazy val d = i3 flatMapR f2
|
||||
val f3: i3.Map[Result] => Task[Any] = {
|
||||
case Value(aa) :^: Value(bb) :^: Value(cc) :^: MNil => new Pure(() => aa + " " + bb + " " + cc)
|
||||
case x => d2
|
||||
}
|
||||
lazy val d3= flat("d3")(i3)(f3)
|
||||
lazy val d3= i3 flatMapR f3
|
||||
|
||||
def d4(i: Int): Task[Int] = flat("d4")(MNil){ _ => val x = math.random; if(x < 0.01) pure(x.toString)(i); else d4(i+1) }
|
||||
|
||||
lazy val pureEval =
|
||||
new (Pure ~> Result) {
|
||||
def apply[T](p: Pure[T]): Result[T] =
|
||||
try { Value(p.eval()) }
|
||||
catch { case e: Exception => throw Incomplete(Incomplete.Error, directCause = Some(e)) }
|
||||
}
|
||||
|
||||
lazy val resultA = d.f( d.in.map(pureEval) )
|
||||
|
||||
def execute[T](root: Task[T]) = {
|
||||
val (service, shutdown) = CompletionService[Task[_], Completed](2)
|
||||
implicit val wrapped = CompletionService.manage(service)(x => println("Starting: " + x), x => println("Finished: " + x) )
|
||||
|
||||
val x = new Execute[Task](true)(taskToNode)
|
||||
try { x.run(root) } finally { shutdown(); println(x.dump) }
|
||||
}
|
||||
def d4(i: Int): Task[Int] = MNil flatMap { _ => val x = math.random; if(x < 0.01) pure(i); else d4(i+1) }
|
||||
|
||||
def go()
|
||||
{
|
||||
def run[T](root: Task[T]) =
|
||||
println("Result : " + execute(root))
|
||||
println("Result : " + Task.run(root, true, 2))
|
||||
|
||||
run(a)
|
||||
run(b)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import xsbt._
|
||||
import sbt._
|
||||
|
||||
import org.scalacheck._
|
||||
import Prop._
|
||||
import TaskGen._
|
||||
import Task._
|
||||
|
||||
object TaskRunnerCallTest extends Properties("TaskRunner Call")
|
||||
{
|
||||
|
|
@ -11,7 +12,7 @@ object TaskRunnerCallTest extends Properties("TaskRunner Call")
|
|||
val f = fibDirect(i)
|
||||
("Workers: " + workers) |: ("i: " + i) |: ("fib(i): " + f) |:
|
||||
{
|
||||
def result = TaskRunner( fibTask(i), workers)
|
||||
def result = tryRun( fibTask(i), false, workers)
|
||||
checkResult(result, f)
|
||||
}
|
||||
}
|
||||
|
|
@ -23,11 +24,11 @@ object TaskRunnerCallTest extends Properties("TaskRunner Call")
|
|||
(index, x1, x2) =>
|
||||
{
|
||||
if(index == i)
|
||||
Task(x2)
|
||||
pure(x2)
|
||||
else
|
||||
iterate( (index+1, x2, x1+x2) )
|
||||
}
|
||||
def iterate(iteration: (Int,Int,Int)) = Task( iteration ) bind Function.tupled(next)
|
||||
def iterate(iteration: (Int,Int,Int)) = pure( iteration ) flatMap next.tupled
|
||||
iterate( (1, 0, 1) )
|
||||
}
|
||||
final def fibDirect(i: Int): Int =
|
||||
|
|
|
|||
|
|
@ -1,8 +1,13 @@
|
|||
import xsbt._
|
||||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009, 2010 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import org.scalacheck._
|
||||
import Prop._
|
||||
import TaskGen._
|
||||
import Task._
|
||||
import Types._
|
||||
|
||||
object TaskRunnerSortTest extends Properties("TaskRunnerSort")
|
||||
{
|
||||
|
|
@ -12,31 +17,33 @@ object TaskRunnerSortTest extends Properties("TaskRunnerSort")
|
|||
java.util.Arrays.sort(sorted)
|
||||
("Workers: " + workers) |: ("Array: " + a.toList) |:
|
||||
{
|
||||
def result = TaskRunner( sort(a.toArray), if(workers > 0) workers else 1)
|
||||
def result = tryRun( sort(a.toSeq), false, if(workers > 0) workers else 1)
|
||||
checkResult(result.toList, sorted.toList)
|
||||
}
|
||||
}
|
||||
final def sortDirect(a: RandomAccessSeq[Int]): RandomAccessSeq[Int] =
|
||||
final def sortDirect(a: Seq[Int]): Seq[Int] =
|
||||
{
|
||||
if(a.length < 2)
|
||||
a
|
||||
else
|
||||
{
|
||||
val pivot = a(0)
|
||||
val (lt,gte) = a.projection.drop(1).partition(_ < pivot)
|
||||
val (lt,gte) = a.view.drop(1).partition(_ < pivot)
|
||||
sortDirect(lt) ++ List(pivot) ++ sortDirect(gte)
|
||||
}
|
||||
}
|
||||
final def sort(a: RandomAccessSeq[Int]): Task[RandomAccessSeq[Int]] =
|
||||
final def sort(a: Seq[Int]): Task[Seq[Int]] =
|
||||
{
|
||||
if(a.length < 200)
|
||||
Task(sortDirect(a))
|
||||
pure(sortDirect(a))
|
||||
else
|
||||
{
|
||||
Task(a) bind { a =>
|
||||
pure(a) flatMap { a =>
|
||||
val pivot = a(0)
|
||||
val (lt,gte) = a.projection.drop(1).partition(_ < pivot)
|
||||
(sort(lt), sort(gte)) map { _ ++ List(pivot) ++ _ }
|
||||
val (lt,gte) = a.view.drop(1).partition(_ < pivot)
|
||||
sort(lt) :^: sort(gte) :^: MNil mapH {
|
||||
case l :+: g :+: HNil => l ++ List(pivot) ++ g
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
package xsbt
|
||||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2009 Mark Harrah
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import org.scalacheck.Prop._
|
||||
|
||||
|
|
@ -14,8 +17,8 @@ object checkResult
|
|||
}
|
||||
catch
|
||||
{
|
||||
case TasksFailed(failures) =>
|
||||
failures.foreach(f => f.exception.printStackTrace)
|
||||
case i: Incomplete =>
|
||||
println(Incomplete.show(i, true))
|
||||
"One or more tasks failed" |: false
|
||||
case e =>
|
||||
e.printStackTrace
|
||||
|
|
|
|||
Loading…
Reference in New Issue