diff --git a/core/actor/src/main/scala/net/liftweb/actor/LAFuture.scala b/core/actor/src/main/scala/net/liftweb/actor/LAFuture.scala index 397357dfb5..33b4a4c43a 100644 --- a/core/actor/src/main/scala/net/liftweb/actor/LAFuture.scala +++ b/core/actor/src/main/scala/net/liftweb/actor/LAFuture.scala @@ -330,25 +330,29 @@ object LAFuture { * collected futures are satisfied */ def collect[T](future: LAFuture[T]*): LAFuture[List[T]] = { - val sync = new Object - val len = future.length - val vals = new collection.mutable.ArrayBuffer[Box[T]](len) - // pad array so inserts at random places are possible - for (i <- 0 to len) { vals.insert(i, Empty) } - var gotCnt = 0 val ret = new LAFuture[List[T]] - - future.toList.zipWithIndex.foreach { - case (f, idx) => - f.foreach { - v => sync.synchronized { - vals.insert(idx, Full(v)) - gotCnt += 1 - if (gotCnt >= len) { - ret.satisfy(vals.toList.flatten) + if (future.isEmpty) { + ret.satisfy(Nil) + } else { + val sync = new Object + val len = future.length + val vals = new collection.mutable.ArrayBuffer[Box[T]](len) + // pad array so inserts at random places are possible + for (i <- 0 to len) { vals.insert(i, Empty) } + var gotCnt = 0 + + future.toList.zipWithIndex.foreach { + case (f, idx) => + f.foreach { + v => sync.synchronized { + vals.insert(idx, Full(v)) + gotCnt += 1 + if (gotCnt >= len) { + ret.satisfy(vals.toList.flatten) + } } } - } + } } ret @@ -362,33 +366,37 @@ object LAFuture { * returned future with an Empty */ def collectAll[T](future: LAFuture[Box[T]]*): LAFuture[Box[List[T]]] = { - val sync = new Object - val len = future.length - val vals = new collection.mutable.ArrayBuffer[Box[T]](len) - // pad array so inserts at random places are possible - for (i <- 0 to len) { vals.insert(i, Empty) } - var gotCnt = 0 val ret = new LAFuture[Box[List[T]]] + if (future.isEmpty) { + ret.satisfy(Full(Nil)) + } else { + val sync = new Object + val len = future.length + val vals = new collection.mutable.ArrayBuffer[Box[T]](len) + // pad array so inserts at random places are possible + for (i <- 0 to len) { vals.insert(i, Empty) } + var gotCnt = 0 + + future.toList.zipWithIndex.foreach { + case (f, idx) => + f.foreach { + vb => sync.synchronized { + vb match { + case Full(v) => { + vals.insert(idx, Full(v)) + gotCnt += 1 + if (gotCnt >= len) { + ret.satisfy(Full(vals.toList.flatten)) + } + } - future.toList.zipWithIndex.foreach { - case (f, idx) => - f.foreach { - vb => sync.synchronized { - vb match { - case Full(v) => { - vals.insert(idx, Full(v)) - gotCnt += 1 - if (gotCnt >= len) { - ret.satisfy(Full(vals.toList.flatten)) + case eb: EmptyBox => { + ret.satisfy(eb) } } - - case eb: EmptyBox => { - ret.satisfy(eb) - } } } - } + } } ret diff --git a/core/actor/src/test/scala/net/liftweb/actor/LAFutureSpec.scala b/core/actor/src/test/scala/net/liftweb/actor/LAFutureSpec.scala new file mode 100644 index 0000000000..ed5cc5e62d --- /dev/null +++ b/core/actor/src/test/scala/net/liftweb/actor/LAFutureSpec.scala @@ -0,0 +1,37 @@ +package net.liftweb.actor + +import org.specs2.mutable.Specification + +class LAFutureSpec extends Specification { + val timeout = 1000L + + "LAFuture" should { + + "collect one future result" in { + val givenOneResult = 123 + val one = LAFuture(() => givenOneResult) + LAFuture.collect(one).get(timeout) shouldEqual List(givenOneResult) + } + + "collect more future results in correct order" in { + val givenOneResult = 123 + val givenTwoResult = 234 + val one = LAFuture(() => givenOneResult) + val two = LAFuture(() => givenTwoResult) + LAFuture.collect(one, two).get shouldEqual List(givenOneResult, givenTwoResult) + } + + "collect empty list immediately" in { + val collectResult = LAFuture.collect(Nil: _*) + collectResult.isSatisfied shouldEqual true + collectResult.get shouldEqual Nil + } + + "collectAll empty list immediately" in { + val collectResult = LAFuture.collectAll(Nil : _*) + collectResult.isSatisfied shouldEqual true + collectResult.get shouldEqual Nil + } + } + +}