-
Notifications
You must be signed in to change notification settings - Fork 0
/
Z2ioTest.scala
91 lines (77 loc) · 2.37 KB
/
Z2ioTest.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package org.lamedh.z2io.core
import org.lamedh.z2io.core.Z2IO.IO
import org.scalatest.AsyncFunSuite
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import org.scalatest.TestSuite
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
class Z2ioTest extends AsyncFunSuite with Matchers {
import Z2ioTest._
test("for comprehension") {
for_2_IO.unsafeRunSync() shouldBe 2
}
test("error handling") {
handler_4_0_IO.unsafeRunSync() shouldBe (4, 0)
}
test("stack safety with trampoline") {
// Executing untrampolined version (with n = 500000) will blow the stack
// def sum(n: Long) = if (n > 0) n + sum(n - 1) else 0
// Also note that below is how not to do trampoline either:
// def sum(n: Long): IO[Long]
// if (n == 0) IO.pure(0) else sum(n - 1).map((l: Long) => l + n)
// Tip: recursive call should be inside lambda
def sum(n: Long): IO[Long] =
if (n == 0) IO.pure(0)
else IO.pure(n).flatMap(p => sum(n - 1).map(_ + n))
sum(500000).unsafeRunSync() shouldBe 125000250000L
}
test("async: callback is called") {
var _2 = 0
for_2_IO.unsafeRunAsync {
case Right(v) => _2 = v
case _ =>
}
_2 shouldBe 2
}
test("async: handle error flow") {
var _4_0 = (0, 0)
handler_4_0_IO.unsafeRunAsync {
case Right(tup) => _4_0 = tup
case _ =>
}
_4_0 shouldBe (4, 0)
}
test("async: handle error") {
var left = false
IO { throw new Exception("Boom"); 5 }.unsafeRunAsync {
case Left(_) => left = true
case _ =>
}
left shouldBe true
}
test("from future and back to future") {
IO.fromFuture(Future.successful(5))
.unsafeToFuture
.map(_ shouldBe 5)
}
}
object Z2ioTest {
val for_2_IO = for {
_0 <- IO(0)
_1 <- IO(_0 + 1)
_2 <- IO(_1 + 1)
} yield _2
def handler_4_0_IO = {
var (must4, never) = (0, 0)
val io = for {
_ <- IO(must4 += 1).handleError(_ => never += 1) // must4: 1, never: 0
_ <- IO(must4 += 1).handleError(_ => never += 1) // must4: 2, never: 0
_ <- IO(throw new Exception("Boom")).handleError(_ => must4 += 1) // must4: 3, never: 0
_ <- IO.raise(new Exception("Boom"))
_ <- IO(never += 1) // must4: 3, never: 0
} yield (must4, never)
io.handleError(_ => must4 += 1 /* must4: 4, never: 0 */ ) *> IO(must4 -> never)
}
}