Skip to content

Commit aa225e2

Browse files
committed
test(coroutine): add basic coroutine test cases
- Create CoroutinesBasic test class - Add tests for basic coroutine concepts: - First coroutine - Suspend function - Coroutine context - withContext usage - Concurrent execution - Controllability of concurrent tasks - Include comments for better understanding of each test case
1 parent e9f57f0 commit aa225e2

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package com.sinlov.kotlin.playground.coroutine
2+
3+
import io.kotest.core.spec.style.FunSpec
4+
import io.kotest.matchers.shouldBe
5+
import kotlinx.coroutines.Dispatchers
6+
import kotlinx.coroutines.async
7+
import kotlinx.coroutines.coroutineScope
8+
import kotlinx.coroutines.delay
9+
import kotlinx.coroutines.launch
10+
import kotlinx.coroutines.runBlocking
11+
import kotlinx.coroutines.withContext
12+
13+
/**
14+
* doc list:
15+
* [Coroutines guide](https://kotlinlang.org/docs/coroutines-guide.html)
16+
* [Coroutines basics](https://kotlinlang.org/docs/coroutines-basics.html)
17+
* [Coroutines and channels − tutorial](https://kotlinlang.org/docs/coroutines-and-channels.html)
18+
*/
19+
class CoroutinesBasic : FunSpec({
20+
21+
test("first coroutine") {
22+
var foo = 0
23+
runBlocking {
24+
launch {
25+
delay(1000L)
26+
println("World!")
27+
foo++
28+
foo shouldBe 1
29+
}
30+
println("Hello,")
31+
foo shouldBe 0
32+
}
33+
}
34+
35+
test("run suspend") {
36+
var foo = 0
37+
suspend fun doWorld() {
38+
delay(1000L)
39+
foo++
40+
println(", coroutines!!")
41+
foo shouldBe 1
42+
}
43+
async { doWorld() }
44+
foo shouldBe 0
45+
}
46+
47+
test("coroutine context") {
48+
var foo = 0
49+
50+
/**
51+
* Its function is to create a [coroutineScope], execute the coroutines inside it,
52+
* and exit after all coroutines have been executed.
53+
* The first parameter is the [kotlin.coroutines.CoroutineContext] specified for the coroutine to run.
54+
*/
55+
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
56+
launch(Dispatchers.Default) {
57+
delay(1000L)
58+
foo++
59+
println(", coroutines!!")
60+
foo shouldBe 1
61+
}
62+
println("Hello")
63+
}
64+
async { doWorld() }
65+
foo shouldBe 0
66+
}
67+
68+
test("coroutine withContext") {
69+
var foo = 0
70+
71+
/**
72+
* more info see [withContext](https://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/with-context.html)
73+
*/
74+
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
75+
launch {
76+
withContext(Dispatchers.Default) {
77+
delay(1000L)
78+
foo++
79+
println(", coroutines!!")
80+
foo shouldBe 1
81+
}
82+
}
83+
println("Hello")
84+
}
85+
async { doWorld() }
86+
foo shouldBe 0
87+
}
88+
89+
test("concurrently executes both sections") {
90+
var foo = 0
91+
92+
/**
93+
* We here have pseudo-concurrency;
94+
* we have not specified any threads, and both coroutines are running within the main thread by [Thread.currentThread].
95+
* However, they do not interfere with each other, nor do they cause any blocking.
96+
* They are indeed "running simultaneously."
97+
*/
98+
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
99+
launch {
100+
delay(2000L)
101+
foo++
102+
println(", coroutine #2, comes later!")
103+
foo shouldBe 2
104+
}
105+
launch {
106+
delay(1000L)
107+
foo++
108+
println(", coroutine #1, here I am!")
109+
foo shouldBe 1
110+
}
111+
print("Hello")
112+
}
113+
async { doWorld() }
114+
foo shouldBe 0
115+
}
116+
117+
test("concurrently Controllability") {
118+
var foo = 0
119+
120+
/**
121+
* Deferred is a subclass of Job, with the unique feature of obtaining the return result of a coroutine.
122+
* Through its [kotlinx.coroutines.Deferred.await] function, it can "synchronously wait" for the coroutine result to return.
123+
* launch can wait for the coroutine to complete through Job, but cannot obtain the coroutine's return result.
124+
* This is the biggest difference between [launch] and [async].
125+
*/
126+
suspend fun doWorld() = coroutineScope {
127+
val job = launch {
128+
delay(2000L)
129+
foo++
130+
println(" and coroutine #2")
131+
foo shouldBe 2
132+
}
133+
launch {
134+
delay(1000L)
135+
foo++
136+
println("from coroutine #1 !")
137+
foo shouldBe 1
138+
}
139+
println("Hello")
140+
job.join()
141+
println("All jobs done.")
142+
foo shouldBe 2
143+
}
144+
145+
async { doWorld() }
146+
foo shouldBe 0
147+
}
148+
})

0 commit comments

Comments
 (0)