Skip to content

Instantly share code, notes, and snippets.

@leandrob13
Created February 25, 2018 02:08
Show Gist options
  • Save leandrob13/c7e35a791ea254f0ab6f8e9b5b0800f6 to your computer and use it in GitHub Desktop.
Save leandrob13/c7e35a791ea254f0ab6f8e9b5b0800f6 to your computer and use it in GitHub Desktop.
import minitest.SimpleTestSuite
import monix.execution.Scheduler
object TaskLocalSuite extends SimpleTestSuite {
implicit val ec: Scheduler = monix.execution.Scheduler.Implicits.global
implicit val opts = Task.defaultOptions.enableLocalContextPropagation
testAsync("TaskLocal.bind clears local with no async boundary") {
val local = TaskLocal(0)
def add(i: Int) = {
local.read.map(_ + i)
}
val res = for {
_ <- local.read.map(assertEquals(_, 0))
_ <- local.bind(1)(add(1)).map(assertEquals(_, 2))
_ <- local.read.map(assertEquals(_, 0))
} yield ()
// Works without the runAsyncOpt because it is not
// jumping to an async boundary
// When taking into consideration local vars, always
// use runAsyncOpt. This is just for illustration purposes
res.runAsync
}
testAsync("TaskLocal.bind clears local in forked thread") {
val local = TaskLocal(0)
def add(i: Int) = {
local.read.map(_ + i)
}
val res = for {
_ <- local.read.map(assertEquals(_, 0))
_ <- local.bind(1)(add(1).executeWithFork).map(assertEquals(_, 2))
_ <- local.read.map(assertEquals(_, 0))
} yield ()
// Must use runAsyncOpt because of async boundary
// Introduced by forked task.
res.runAsyncOpt
}
test("TaskLocal.bind clears current local in current thread") {
import scala.concurrent.Await
import scala.concurrent.duration._
val local = TaskLocal(0)
def add(i: Int) = {
local.read.map(_ + i)
}
//Basically we do the same checks as before but blocking
//to explicitly check the status of the local in the
//current execution thread
assertEquals(local.read.coeval.value, Right(0))
val res = Await.result(local.bind(1)(add(1)).runAsyncOpt, 5.seconds)
assertEquals(res, 2)
//clears the local as expected
assertEquals(local.read.coeval.value, Right(0))
}
test("TaskLocal.bind does not clear current local in forked thread") {
import scala.concurrent.Await
import scala.concurrent.duration._
val local = TaskLocal(0)
def add(i: Int) = {
local.read.map(_ + i)
}
//We do the current local var
assertEquals(local.read.coeval.value, Right(0))
//Bind clears the local in the forked thread
//Which means it doesn't do the proper cleanup
val res = Await.result(local.bind(1)(add(1).executeWithFork).runAsyncOpt, 5.seconds)
assertEquals(res, 2)
// And leaves the current local var with 1
assertEquals(local.read.coeval.value, Right(1))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment