Skip to content

Commit 381f1b5

Browse files
hanggaHangga Aji Sayektitheangrydev
authored
KTLN-772 - Kotlin Coroutine Continuation - resolve (#983)
* update sample * rename * add sample with async * simplify apply * sip * using slf4j * using resumewith * add sample aritmatic * increase throw potentially * add sample * sip * skip * add do something * move to new module * remove continuation package on module3 * simplifying test * unit test to live test * Update core-kotlin-modules/core-kotlin-concurrency-4/src/test/kotlin/com/baeldung/continuation/ContinuationLiveTest.kt Co-authored-by: Liam Williams <[email protected]> * update, resolve * add some assertion * unused import * update * reorder by topic --------- Co-authored-by: Hangga Aji Sayekti <[email protected]> Co-authored-by: Liam Williams <[email protected]>
1 parent 44feb92 commit 381f1b5

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
<parent>
7+
<groupId>com.baeldung</groupId>
8+
<artifactId>core-kotlin-modules</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
</parent>
11+
12+
<artifactId>core-kotlin-concurrency-4</artifactId>
13+
14+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package com.baeldung.continuation
2+
3+
import kotlinx.coroutines.*
4+
import org.junit.jupiter.api.Test
5+
import org.junit.jupiter.api.assertThrows
6+
import org.slf4j.LoggerFactory
7+
import java.net.HttpURLConnection
8+
import java.net.URL
9+
import kotlin.coroutines.Continuation
10+
import kotlin.coroutines.resume
11+
import kotlin.coroutines.resumeWithException
12+
import kotlin.coroutines.suspendCoroutine
13+
import kotlin.test.assertEquals
14+
15+
class ContinuationLiveTest {
16+
17+
private val logger = LoggerFactory.getLogger("")
18+
19+
private suspend fun doWork(name: String, delay: Long): String {
20+
logger.info("$name started")
21+
delay(delay)
22+
logger.info("$name resumed")
23+
return name
24+
}
25+
26+
@Test
27+
fun `prove suspending`() = runBlocking {
28+
val dispatcher = Dispatchers.Default
29+
30+
val job1 = async(dispatcher) {
31+
doWork("Job 1", 2000)
32+
}
33+
34+
val job2 = async(dispatcher) {
35+
doWork("Job 2", 600)
36+
}
37+
38+
val job3 = async(dispatcher) {
39+
doWork("Job 3", 100)
40+
}
41+
42+
assertEquals("Job 1", job1.await())
43+
assertEquals("Job 2", job2.await())
44+
assertEquals("Job 3", job3.await())
45+
46+
logger.info("All coroutines finished!")
47+
}
48+
49+
@Test
50+
fun `test create continuation manually`(): Unit = runBlocking {
51+
val simpleContinuation = Continuation<Int>(Dispatchers.IO) { result ->
52+
assertEquals(45, result.getOrNull())
53+
}
54+
simpleContinuation.resumeWith(Result.success(45))
55+
}
56+
57+
@Test
58+
fun `test continuation using suspendCoroutine`() = runBlocking {
59+
val result = suspendCoroutine { continuation ->
60+
continuation.resumeWith(Result.success("Baeldung"))
61+
}
62+
assertEquals("Baeldung", result)
63+
}
64+
65+
private suspend fun usingResumeWith(url: String): String {
66+
return withContext(Dispatchers.IO) {
67+
suspendCoroutine { continuation ->
68+
val result = try {
69+
val connection = (URL(url).openConnection() as HttpURLConnection).apply {
70+
requestMethod = "GET"
71+
connectTimeout = 5000
72+
readTimeout = 5000
73+
}
74+
75+
val responseCode = connection.responseCode
76+
if (responseCode == HttpURLConnection.HTTP_OK) {
77+
Result.success("$responseCode")
78+
} else {
79+
Result.failure(Exception("$responseCode - Failed"))
80+
}
81+
} catch (e: Exception) {
82+
Result.failure(Exception(e.message))
83+
}
84+
85+
continuation.resumeWith(result)
86+
}
87+
}
88+
}
89+
90+
@Test
91+
fun `test continuation using suspendFunction network call success for usingResumeWith`() = runBlocking {
92+
assertEquals("200", usingResumeWith("https://hangga.github.io"))
93+
}
94+
95+
@Test
96+
fun `test continuation using suspendFunction network call failure for usingResumeWith`() = runBlocking {
97+
val thrown = assertThrows<Exception> {
98+
usingResumeWith("https://hangga.github.io/fail")
99+
}
100+
assertEquals("404 - Failed", thrown.message)
101+
}
102+
103+
@Test
104+
fun `test invalid URL for usingResumeWith`() = runBlocking {
105+
val thrown = assertThrows<Exception> {
106+
usingResumeWith("invalid-url")
107+
}
108+
assertEquals("no protocol: invalid-url", thrown.message)
109+
}
110+
111+
@Test
112+
fun `test timeout for usingResumeWith`() = runBlocking {
113+
val thrown = assertThrows<Exception> {
114+
usingResumeWith("https://10.255.255.1")
115+
}
116+
assertEquals("Connect timed out", thrown.message)
117+
}
118+
119+
private suspend fun usingResumeAndResumeWithException(url: String): String {
120+
return withContext(Dispatchers.IO) {
121+
suspendCoroutine { continuation ->
122+
try {
123+
val connection = (URL(url).openConnection() as HttpURLConnection).apply {
124+
requestMethod = "GET"
125+
connectTimeout = 5000
126+
readTimeout = 5000
127+
}
128+
129+
val responseCode = connection.responseCode
130+
if (responseCode == HttpURLConnection.HTTP_OK) {
131+
continuation.resume("$responseCode")
132+
} else {
133+
continuation.resumeWithException(Exception("HTTP response code $responseCode - Failed"))
134+
}
135+
} catch (e: Exception) {
136+
continuation.resumeWithException(Exception(e.message))
137+
}
138+
}
139+
}
140+
}
141+
142+
@Test
143+
fun `test continuation using suspendFunction network call success for usingResumeAndResumeWithException`() = runBlocking {
144+
assertEquals("200", usingResumeAndResumeWithException("https://hangga.github.io"))
145+
}
146+
147+
@Test
148+
fun `test continuation using suspendFunction network call failure for usingResumeAndResumeWithException`() = runBlocking {
149+
val thrown = assertThrows<Exception> {
150+
usingResumeAndResumeWithException("https://hangga.github.io/fail")
151+
}
152+
assertEquals("HTTP response code 404 - Failed", thrown.message)
153+
}
154+
155+
@Test
156+
fun `test invalid URL for usingResumeAndResumeWithException`() = runBlocking {
157+
val thrown = assertThrows<Exception> {
158+
usingResumeAndResumeWithException("invalid-url")
159+
}
160+
assertEquals("no protocol: invalid-url", thrown.message)
161+
}
162+
163+
@Test
164+
fun `test timeout for usingResumeAndResumeWithException`() = runBlocking {
165+
val thrown = assertThrows<Exception> {
166+
usingResumeAndResumeWithException("https://10.255.255.1") // An IP address that will timeout
167+
}
168+
assertEquals("Connect timed out", thrown.message)
169+
}
170+
}

core-kotlin-modules/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@
7070
<module>core-kotlin-files</module>
7171
<module>core-kotlin-operators</module>
7272
<module>core-kotlin-concurrency-3</module>
73+
<module>core-kotlin-concurrency-4</module>
7374
</modules>
7475

7576
</project>

0 commit comments

Comments
 (0)