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
+ }
0 commit comments