blob: 30646a67558e3d33c6beb535d05bc9eefa7dfd51 (
plain) (
tree)
|
|
/*
* Copyright (C) 2012-2014-2013 Typesafe Inc. <http://www.typesafe.com>
*/
package scala.async
package run
package live
import org.junit.Test
import internal.AsyncTestLV
import AsyncTestLV._
case class Cell[T](v: T)
class Meter(val len: Long) extends AnyVal
case class MCell[T](var v: T)
class LiveVariablesSpec {
AsyncTestLV.clear()
@Test
def `zero out fields of reference type`() {
val f = async { Cell(1) }
def m1(x: Cell[Int]): Cell[Int] =
async { Cell(x.v + 1) }
def m2(x: Cell[Int]): String =
async { x.v.toString }
def m3() = async {
val a: Cell[Int] = await(f) // await$1$1
// a == Cell(1)
val b: Cell[Int] = await(m1(a)) // await$2$1
// b == Cell(2)
assert(AsyncTestLV.log.exists(_._2 == Cell(1)), AsyncTestLV.log)
val res = await(m2(b)) // await$3$1
assert(AsyncTestLV.log.exists(_._2 == Cell(2)))
res
}
assert(m3() == "2")
}
@Test
def `zero out fields of type Any`() {
val f = async { Cell(1) }
def m1(x: Cell[Int]): Cell[Int] =
async { Cell(x.v + 1) }
def m2(x: Any): String =
async { x.toString }
def m3() = async {
val a: Cell[Int] = await(f) // await$4$1
// a == Cell(1)
val b: Any = await(m1(a)) // await$5$1
// b == Cell(2)
assert(AsyncTestLV.log.exists(_._2 == Cell(1)))
val res = await(m2(b)) // await$6$1
assert(AsyncTestLV.log.exists(_._2 == Cell(2)))
res
}
assert(m3() == "Cell(2)")
}
@Test
def `do not zero out fields of primitive type`() {
val f = async { 1 }
def m1(x: Int): Cell[Int] =
async { Cell(x + 1) }
def m2(x: Any): String =
async { x.toString }
def m3() = async {
val a: Int = await(f) // await$7$1
// a == 1
val b: Any = await(m1(a)) // await$8$1
// b == Cell(2)
// assert(!AsyncTestLV.log.exists(p => p._1 == "await$7$1"))
val res = await(m2(b)) // await$9$1
assert(AsyncTestLV.log.exists(_._2 == Cell(2)))
res
}
assert(m3() == "Cell(2)")
}
@Test
def `zero out fields of value class type`() {
val f = async { Cell(1) }
def m1(x: Cell[Int]): Meter =
async { new Meter(x.v + 1) }
def m2(x: Any): String =
async { x.toString }
def m3() = async {
val a: Cell[Int] = await(f) // await$10$1
// a == Cell(1)
val b: Meter = await(m1(a)) // await$11$1
// b == Meter(2)
assert(AsyncTestLV.log.exists(_._2 == Cell(1)))
val res = await(m2(b.len)) // await$12$1
assert(AsyncTestLV.log.exists(_._2.asInstanceOf[Meter].len == 2L))
res
}
assert(m3() == "2")
}
@Test
def `zero out fields after use in loop`() {
val f = async { MCell(1) }
def m1(x: MCell[Int], y: Int): Int =
async { x.v + y }
def m3() = async {
// state #1
val a: MCell[Int] = await(f) // await$13$1
// state #2
var y = MCell(0)
while (a.v < 10) {
// state #4
a.v = a.v + 1
y = MCell(await(a).v + 1) // await$14$1
// state #7
}
// state #3
// assert(AsyncTestLV.log.exists(entry => entry._1 == "await$14$1"))
val b = await(m1(a, y.v)) // await$15$1
// state #8
assert(AsyncTestLV.log.exists(_._2 == MCell(10)), AsyncTestLV.log)
assert(AsyncTestLV.log.exists(_._2 == MCell(11)))
b
}
assert(m3() == 21, m3())
}
@Test
def `don't zero captured fields captured lambda`() {
val f = async {
val x = "x"
val y = "y"
await(0)
y.reverse
val f = () => assert(x != null)
await(0)
f
}
AsyncTestLV.assertNotNulledOut("x")
AsyncTestLV.assertNulledOut("y")
f()
}
@Test
def `don't zero captured fields captured by-name`() {
def func0[A](a: => A): () => A = () => a
val f = async {
val x = "x"
val y = "y"
await(0)
y.reverse
val f = func0(assert(x != null))
await(0)
f
}
AsyncTestLV.assertNotNulledOut("x")
AsyncTestLV.assertNulledOut("y")
f()
}
@Test
def `don't zero captured fields nested class`() {
def func0[A](a: => A): () => A = () => a
val f = async {
val x = "x"
val y = "y"
await(0)
y.reverse
val f = new Function0[Unit] {
def apply = assert(x != null)
}
await(0)
f
}
AsyncTestLV.assertNotNulledOut("x")
AsyncTestLV.assertNulledOut("y")
f()
}
@Test
def `don't zero captured fields nested object`() {
def func0[A](a: => A): () => A = () => a
val f = async {
val x = "x"
val y = "y"
await(0)
y.reverse
object f extends Function0[Unit] {
def apply = assert(x != null)
}
await(0)
f
}
AsyncTestLV.assertNotNulledOut("x")
AsyncTestLV.assertNulledOut("y")
f()
}
@Test
def `don't zero captured fields nested def`() {
val f = async {
val x = "x"
val y = "y"
await(0)
y.reverse
def xx = x
val f = xx _
await(0)
f
}
AsyncTestLV.assertNotNulledOut("x")
AsyncTestLV.assertNulledOut("y")
f()
}
@Test
def `capture bug`() {
sealed trait Base
case class B1() extends Base
case class B2() extends Base
val outer = List[(Base, Int)]((B1(), 8))
def getMore(b: Base) = 4
def baz = async {
outer.head match {
case (a @ B1(), r) => {
val ents = await(getMore(a))
{ () =>
println(a)
assert(a ne null)
}
}
case (b @ B2(), x) =>
() => ???
}
}
baz()
}
}
|