blob: a98b6f022b20a80ad6b0ee1d79ea6f05f112174d [file] [log] [blame]
Roman Elizarov41c5c8b2017-01-25 13:37:15 +03001package kotlinx.coroutines.experimental
2
3import org.junit.Test
4import java.io.IOException
Roman Elizarovb6b01252017-02-06 13:17:40 +03005import kotlin.test.assertTrue
Roman Elizarov41c5c8b2017-01-25 13:37:15 +03006
7class DeferTest : TestBase() {
8 @Test
9 fun testSimple(): Unit = runBlocking {
10 expect(1)
11 val d = defer(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030012 expect(3)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030013 42
14 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030015 expect(2)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030016 check(d.isActive)
17 check(d.await() == 42)
18 check(!d.isActive)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030019 expect(4)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030020 check(d.await() == 42) // second await -- same result
Roman Elizarov7cf452e2017-01-29 21:58:33 +030021 finish(5)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030022 }
23
24 @Test(expected = IOException::class)
25 fun testSimpleException(): Unit = runBlocking {
26 expect(1)
27 val d = defer(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030028 finish(3)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030029 throw IOException()
30 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030031 expect(2)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030032 d.await() // will throw IOException
33 }
34
35 @Test(expected = IOException::class)
36 fun testDeferAndYieldException(): Unit = runBlocking {
37 expect(1)
38 val d = defer(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030039 expect(3)
40 yield() // no effect, parent waiting
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030041 finish(4)
42 throw IOException()
43 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030044 expect(2)
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030045 d.await() // will throw IOException
46 }
Roman Elizarovdaa79222017-01-26 11:31:31 +030047
48 @Test
49 fun testDeferWithTwoWaiters() = runBlocking {
50 expect(1)
51 val d = defer(context) {
Roman Elizarov7cf452e2017-01-29 21:58:33 +030052 expect(5)
Roman Elizarovdaa79222017-01-26 11:31:31 +030053 yield()
Roman Elizarov7cf452e2017-01-29 21:58:33 +030054 expect(9)
Roman Elizarovdaa79222017-01-26 11:31:31 +030055 42
56 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030057 expect(2)
Roman Elizarovdaa79222017-01-26 11:31:31 +030058 launch(context) {
59 expect(6)
60 check(d.await() == 42)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030061 expect(11)
Roman Elizarovdaa79222017-01-26 11:31:31 +030062 }
Roman Elizarov7cf452e2017-01-29 21:58:33 +030063 expect(3)
64 launch(context) {
65 expect(7)
66 check(d.await() == 42)
67 expect(12)
68 }
69 expect(4)
Roman Elizarovdaa79222017-01-26 11:31:31 +030070 yield() // this actually yields control to defer, which produces results and resumes both waiters (in order)
Roman Elizarov7cf452e2017-01-29 21:58:33 +030071 expect(8)
72 yield() // yield again to "d", which completes
73 expect(10)
74 yield() // yield to both waiters
75 finish(13)
Roman Elizarovdaa79222017-01-26 11:31:31 +030076 }
Roman Elizarovb6b01252017-02-06 13:17:40 +030077
78 class BadClass {
79 override fun equals(other: Any?): Boolean = error("equals")
80 override fun hashCode(): Int = error("hashCode")
81 override fun toString(): String = error("toString")
82 }
83
84 @Test
85 fun testDeferBadClass() = runBlocking {
86 val bad = BadClass()
87 val d = defer(context) {
88 expect(1)
89 bad
90 }
91 assertTrue(d.await() === bad)
92 finish(2)
93 }
Roman Elizarov41c5c8b2017-01-25 13:37:15 +030094}