Skip to content

Instantly share code, notes, and snippets.

@bpholt
Last active June 28, 2023 16:32
Show Gist options
  • Save bpholt/0085280b52436106267a0bdb1aa4ebce to your computer and use it in GitHub Desktop.
Save bpholt/0085280b52436106267a0bdb1aa4ebce to your computer and use it in GitHub Desktop.
Demonstrates confusing behavior with Cats Effect 3.5, the CE TestKit, and CompletableFutures
//> using scala 2.13
//> using dep org.typelevel::cats-effect-testkit:3.5.1
//> using dep com.eed3si9n.expecty::expecty:0.16.0
import cats.effect._
import cats.effect.kernel.Outcome
import cats.effect.std.Dispatcher
import cats.effect.testkit.TestControl
import cats.syntax.all._
import com.eed3si9n.expecty.Expecty._
import scala.concurrent.duration._
import java.util.concurrent.CompletableFuture
trait JavaInterface {
def foo(i: Int): CompletableFuture[Unit]
}
class CodeUnderTest[F[_]: Async](ji: JavaInterface) {
def useFoo: F[Unit] =
Temporal[F].sleep(1.second) >> Async[F].fromCompletableFuture(Sync[F].delay(ji.foo(42)))
}
object MyApp extends IOApp.Simple {
val shouldItWork: Boolean = true
def run: IO[Unit] =
Dispatcher.sequential[IO].use { dispatcher =>
for {
deferred <- Deferred[IO, Int]
ji = new JavaInterface {
def foo(i: Int): CompletableFuture[Unit] = {
if (shouldItWork) {
dispatcher.unsafeRunSync(deferred.complete(i).void)
CompletableFuture.completedFuture(())
} else
dispatcher.unsafeToCompletableFuture(deferred.complete(i).void)
}
}
control <- TestControl.execute(new CodeUnderTest[IO](ji).useFoo)
_ <- IO.println("pre tick")
_ <- control.tick
_ <- IO.println("pre initial deferred.tryGet")
initialValue <- deferred.tryGet
_ <- IO.println("pre tickFor(1.second)")
_ <- control.tickFor(1.second)
_ <- IO.println("pre get results")
results <- control.results
_ <- IO.println("pre final deferred.get")
finalValue <- deferred.get
_ <- IO.println("done… control.results should be Some(())")
output <- IO {
assert(initialValue == None)
assert(finalValue == 42)
assert(results == Option(Outcome.succeeded[cats.Id, Throwable, Unit](())))
}.attempt
_ <- IO.println(output)
} yield ()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment