blob: baa9a4f688a557b3c1aa33ee30904a57c824ec8e [file] [log] [blame]
Roman Elizarovf106ff32017-05-17 12:22:14 +03001/*
Roman Elizarov1f74a2d2018-06-29 19:19:45 +03002 * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Roman Elizarovf106ff32017-05-17 12:22:14 +03003 */
4
5package kotlinx.coroutines.experimental.guava
6
Roman Elizarov9fe5f462018-02-21 19:05:52 +03007import com.google.common.util.concurrent.*
Roman Elizarovf106ff32017-05-17 12:22:14 +03008import kotlinx.coroutines.experimental.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +03009import kotlinx.coroutines.experimental.CancellationException
10import org.hamcrest.core.*
11import org.junit.*
Roman Elizarovf106ff32017-05-17 12:22:14 +030012import org.junit.Assert.*
Vsevolod Tolstopyatovf2b4e0e2018-05-25 18:58:01 +030013import java.io.*
Roman Elizarov9fe5f462018-02-21 19:05:52 +030014import java.util.concurrent.*
15import kotlin.coroutines.experimental.*
Roman Elizarovf106ff32017-05-17 12:22:14 +030016
17class ListenableFutureTest : TestBase() {
Roman Elizarov45181042017-07-20 20:37:51 +030018 @Before
19 fun setup() {
20 ignoreLostThreads("ForkJoinPool.commonPool-worker-")
21 }
22
Roman Elizarovf106ff32017-05-17 12:22:14 +030023 @Test
24 fun testSimpleAwait() {
25 val service = MoreExecutors.listeningDecorator(ForkJoinPool.commonPool())
26 val future = future {
27 service.submit(Callable<String> {
28 "O"
29 }).await() + "K"
30 }
31 assertThat(future.get(), IsEqual("OK"))
32 }
33
34 @Test
Vsevolod Tolstopyatovf2b4e0e2018-05-25 18:58:01 +030035 fun testAwaitWithContext() = runTest {
36 val future = SettableFuture.create<Int>()
37 val deferred = async(coroutineContext) {
38 withContext(CommonPool) {
39 future.await()
40 }
41 }
42
43 future.set(1)
44 assertEquals(1, deferred.await())
45 }
46
47 @Test
48 fun testAwaitWithContextCancellation() = runTest(expected = {it is JobCancellationException}) {
49 val future = SettableFuture.create<Int>()
50 val deferred = async(coroutineContext) {
51 withContext(CommonPool) {
52 future.await()
53 }
54 }
55
56 deferred.cancel(IOException())
57 deferred.await()
58 }
59
60 @Test
Roman Elizarovf106ff32017-05-17 12:22:14 +030061 fun testCompletedFuture() {
62 val toAwait = SettableFuture.create<String>()
63 toAwait.set("O")
64 val future = future {
65 toAwait.await() + "K"
66 }
67 assertThat(future.get(), IsEqual("OK"))
68 }
69
70 @Test
71 fun testWaitForFuture() {
72 val toAwait = SettableFuture.create<String>()
73 val future = future {
74 toAwait.await() + "K"
75 }
76 assertFalse(future.isDone)
77 toAwait.set("O")
78 assertThat(future.get(), IsEqual("OK"))
79 }
80
81 @Test
82 fun testCompletedFutureExceptionally() {
83 val toAwait = SettableFuture.create<String>()
84 toAwait.setException(IllegalArgumentException("O"))
85 val future = future<String> {
86 try {
87 toAwait.await()
88 } catch (e: RuntimeException) {
89 assertThat(e, IsInstanceOf(IllegalArgumentException::class.java))
90 e.message!!
91 } + "K"
92 }
93 assertThat(future.get(), IsEqual("OK"))
94 }
95
96 @Test
97 fun testWaitForFutureWithException() {
98 val toAwait = SettableFuture.create<String>()
99 val future = future<String> {
100 try {
101 toAwait.await()
102 } catch (e: RuntimeException) {
103 assertThat(e, IsInstanceOf(IllegalArgumentException::class.java))
104 e.message!!
105 } + "K"
106 }
107 assertFalse(future.isDone)
108 toAwait.setException(IllegalArgumentException("O"))
109 assertThat(future.get(), IsEqual("OK"))
110 }
111
112 @Test
113 fun testExceptionInsideCoroutine() {
114 val service = MoreExecutors.listeningDecorator(ForkJoinPool.commonPool())
115 val future = future {
116 if (service.submit(Callable<Boolean> { true }).await()) {
117 throw IllegalStateException("OK")
118 }
119 "fail"
120 }
121 try {
122 future.get()
123 fail("'get' should've throw an exception")
124 } catch (e: ExecutionException) {
125 assertThat(e.cause, IsInstanceOf(IllegalStateException::class.java))
126 assertThat(e.cause!!.message, IsEqual("OK"))
127 }
128 }
129
130 @Test
131 fun testCompletedDeferredAsListenableFuture() = runBlocking {
132 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300133 val deferred = async(coroutineContext, CoroutineStart.UNDISPATCHED) {
Roman Elizarovf106ff32017-05-17 12:22:14 +0300134 expect(2) // completed right away
135 "OK"
136 }
137 expect(3)
138 val future = deferred.asListenableFuture()
139 assertThat(future.await(), IsEqual("OK"))
140 finish(4)
141 }
142
143 @Test
144 fun testWaitForDeferredAsListenableFuture() = runBlocking {
145 expect(1)
Roman Elizarov43e3af72017-07-21 16:01:31 +0300146 val deferred = async(coroutineContext) {
Roman Elizarovf106ff32017-05-17 12:22:14 +0300147 expect(3) // will complete later
148 "OK"
149 }
150 expect(2)
151 val future = deferred.asListenableFuture()
152 assertThat(future.await(), IsEqual("OK")) // await yields main thread to deferred coroutine
153 finish(4)
154 }
155
156 @Test
157 fun testCancellableAwait() = runBlocking {
158 expect(1)
159 val toAwait = SettableFuture.create<String>()
Roman Elizarov43e3af72017-07-21 16:01:31 +0300160 val job = launch(coroutineContext, CoroutineStart.UNDISPATCHED) {
Roman Elizarovf106ff32017-05-17 12:22:14 +0300161 expect(2)
162 try {
163 toAwait.await() // suspends
164 } catch (e: CancellationException) {
165 expect(5) // should throw cancellation exception
166 throw e
167 }
168 }
169 expect(3)
170 job.cancel() // cancel the job
171 toAwait.set("fail") // too late, the waiting job was already cancelled
172 expect(4) // job processing of cancellation was scheduled, not executed yet
173 yield() // yield main thread to job
174 finish(6)
175 }
176}