Skip to content

Commit b52dd18

Browse files
committed
test: 增加几个使用 lincheck 针对并发相关实现的测试
1 parent 152b0d3 commit b52dd18

File tree

6 files changed

+313
-3
lines changed

6 files changed

+313
-3
lines changed

simbot-commons/simbot-common-atomic/build.gradle.kts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Project https://github.com/simple-robot/simpler-robot
55
66
*
7-
* This file is part of the Simple Robot Library.
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
88
*
99
* This program is free software: you can redistribute it and/or modify
1010
* it under the terms of the GNU Lesser General Public License as published by
@@ -82,6 +82,7 @@ kotlin {
8282
jvmTest {
8383
dependencies {
8484
implementation(kotlin("test-junit5"))
85+
implementation(libs.kotlinx.lincheck)
8586
}
8687
}
8788

@@ -94,3 +95,12 @@ kotlin {
9495
}
9596

9697
configWasmJsTest()
98+
99+
// https://book.kotlincn.net/text/testing-strategies.html
100+
tasks.withType<Test> {
101+
jvmArgs(
102+
"--add-opens", "java.base/jdk.internal.misc=ALL-UNNAMED",
103+
"--add-exports", "java.base/jdk.internal.util=ALL-UNNAMED",
104+
"--add-exports", "java.base/sun.security.action=ALL-UNNAMED"
105+
)
106+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright (c) 2024. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
import love.forte.simbot.common.atomic.AtomicULong
25+
import love.forte.simbot.common.atomic.atomic
26+
import love.forte.simbot.common.atomic.atomicUL
27+
import org.jetbrains.kotlinx.lincheck.annotations.Operation
28+
import org.jetbrains.kotlinx.lincheck.check
29+
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
30+
import org.jetbrains.kotlinx.lincheck.strategy.stress.StressOptions
31+
import kotlin.test.Test
32+
33+
/*
34+
* Copyright (c) 2024. ForteScarlet.
35+
*
36+
* Project https://github.com/simple-robot/simpler-robot
37+
38+
*
39+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
40+
*
41+
* This program is free software: you can redistribute it and/or modify
42+
* it under the terms of the GNU Lesser General Public License as published by
43+
* the Free Software Foundation, either version 3 of the License, or
44+
* (at your option) any later version.
45+
*
46+
* This program is distributed in the hope that it will be useful,
47+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
48+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49+
* Lesser GNU General Public License for more details.
50+
*
51+
* You should have received a copy of the Lesser GNU General Public License
52+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
53+
*
54+
*/
55+
56+
abstract class AtomicStressTest {
57+
@Test
58+
fun stressTest() = StressOptions().check(this::class)
59+
@Test
60+
fun modelCheckingTest() = ModelCheckingOptions().check(this::class)
61+
}
62+
63+
class AtomicLongTest : AtomicStressTest() {
64+
private val atomic = atomic(0L)
65+
66+
@Operation
67+
fun inc1() = atomic.getAndIncrement()
68+
69+
@Operation
70+
fun inc2() = atomic.incrementAndGet()
71+
72+
@Operation
73+
fun dec1() = atomic.getAndDecrement()
74+
75+
@Operation
76+
fun dec2() = atomic.decrementAndGet()
77+
78+
@Operation
79+
fun get() = atomic.value
80+
81+
82+
}
83+
84+
class AtomicIntTest : AtomicStressTest() {
85+
private val atomic = atomic(0)
86+
87+
@Operation
88+
fun inc1() = atomic.getAndIncrement()
89+
90+
@Operation
91+
fun inc2() = atomic.incrementAndGet()
92+
93+
@Operation
94+
fun dec1() = atomic.getAndDecrement()
95+
96+
@Operation
97+
fun dec2() = atomic.decrementAndGet()
98+
99+
@Operation
100+
fun get() = atomic.value
101+
}
102+
103+
class AtomicUIntTest : AtomicStressTest() {
104+
private val atomic = atomic(0u)
105+
106+
@Operation
107+
fun inc1() = atomic.getAndIncrement()
108+
109+
@Operation
110+
fun inc2() = atomic.incrementAndGet()
111+
112+
@Operation
113+
fun dec1() = atomic.getAndDecrement()
114+
115+
@Operation
116+
fun dec2() = atomic.decrementAndGet()
117+
118+
@Operation
119+
fun get() = atomic.value
120+
}
121+
122+
class AtomicULongTest : AtomicStressTest() {
123+
private val atomic: AtomicULong = atomicUL(0u)
124+
125+
@Operation
126+
fun inc1() = atomic.getAndIncrement()
127+
128+
@Operation
129+
fun inc2() = atomic.incrementAndGet()
130+
131+
@Operation
132+
fun dec1() = atomic.getAndDecrement()
133+
134+
@Operation
135+
fun dec2() = atomic.decrementAndGet()
136+
137+
@Operation
138+
fun get() = atomic.value
139+
}

simbot-commons/simbot-common-collection/build.gradle.kts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* Project https://github.com/simple-robot/simpler-robot
55
66
*
7-
* This file is part of the Simple Robot Library.
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
88
*
99
* This program is free software: you can redistribute it and/or modify
1010
* it under the terms of the GNU Lesser General Public License as published by
@@ -90,6 +90,7 @@ kotlin {
9090
jvmTest {
9191
dependencies {
9292
implementation(kotlin("test-junit5"))
93+
implementation(libs.kotlinx.lincheck)
9394
}
9495
}
9596

@@ -108,3 +109,12 @@ kotlin {
108109
}
109110

110111
configWasmJsTest()
112+
113+
// https://book.kotlincn.net/text/testing-strategies.html
114+
tasks.withType<Test> {
115+
jvmArgs(
116+
"--add-opens", "java.base/jdk.internal.misc=ALL-UNNAMED",
117+
"--add-exports", "java.base/jdk.internal.util=ALL-UNNAMED",
118+
"--add-exports", "java.base/sun.security.action=ALL-UNNAMED"
119+
)
120+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright (c) 2024. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
package love.forte.simbot.common.collection
25+
26+
import org.jetbrains.kotlinx.lincheck.annotations.Operation
27+
import org.jetbrains.kotlinx.lincheck.annotations.Param
28+
import org.jetbrains.kotlinx.lincheck.check
29+
import org.jetbrains.kotlinx.lincheck.paramgen.IntGen
30+
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
31+
import kotlin.test.Test
32+
33+
34+
/**
35+
*
36+
* @author ForteScarlet
37+
*/
38+
@Param(name = "k", gen = IntGen::class, conf = "1:10")
39+
@Param(name = "v", gen = IntGen::class, conf = "1:20")
40+
class JvmConcurrentMapLincheckTest {
41+
private val map = concurrentMutableMap<Int, Int>()
42+
43+
@Operation
44+
fun put(@Param(name = "k") key: Int, @Param(name = "v") value: Int) =
45+
map.put(key, value)
46+
47+
@Operation
48+
fun computeIfAbsent(@Param(name = "k") key: Int, @Param(name = "v") value: Int) =
49+
map.computeValueIfAbsent(key) { value }
50+
51+
@Operation
52+
fun computeIfPresent(@Param(name = "k") key: Int, @Param(name = "v") value: Int) =
53+
map.computeValueIfPresent(key) { _, _ -> value }
54+
55+
@Operation
56+
fun compute(@Param(name = "k") key: Int, @Param(name = "v") value: Int) =
57+
map.computeValue(key) { _, _ -> value }
58+
59+
@Operation
60+
fun remove(@Param(name = "k") key: Int) =
61+
map.remove(key)
62+
63+
@Operation
64+
fun remove(@Param(name = "k") key: Int, @Param(name = "v") value: Int) =
65+
map.removeValue(key) { value }
66+
67+
@Operation
68+
fun get(@Param(name = "k") key: Int) = map[key]
69+
70+
@Test
71+
fun modelCheckingTest() = ModelCheckingOptions().check(this::class)
72+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright (c) 2024. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
package love.forte.simbot.common.collection
25+
26+
import org.jetbrains.kotlinx.lincheck.annotations.Operation
27+
import org.jetbrains.kotlinx.lincheck.annotations.Param
28+
import org.jetbrains.kotlinx.lincheck.check
29+
import org.jetbrains.kotlinx.lincheck.paramgen.IntGen
30+
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
31+
import kotlin.test.Test
32+
33+
abstract class JvmConcurrentQueueLincheckTests {
34+
@Test
35+
open fun modelCheckingTest() = ModelCheckingOptions().check(this::class)
36+
}
37+
38+
@OptIn(ExperimentalSimbotCollectionApi::class)
39+
@Param(name = "e", gen = IntGen::class, conf = "1:5")
40+
class JvmConcurrentQueueLincheckTest : JvmConcurrentQueueLincheckTests() {
41+
private val queue = createConcurrentQueue<Int>()
42+
43+
@Operation
44+
fun add(@Param(name = "e") e: Int) = queue.add(e)
45+
46+
@Operation
47+
fun remove(@Param(name = "e") e: Int) = queue.remove(e)
48+
49+
@Operation
50+
fun removeIf(@Param(name = "e") e: Int) = queue.removeIf { it == e }
51+
}
52+
53+
@OptIn(ExperimentalSimbotCollectionApi::class)
54+
@Param(name = "e", gen = IntGen::class, conf = "1:5")
55+
@Param(name = "priority", gen = IntGen::class, conf = "1:5")
56+
class JvmPriorityConcurrentQueueLincheckTest : JvmConcurrentQueueLincheckTests() {
57+
private val queue = createPriorityConcurrentQueue<Int>()
58+
59+
@Operation
60+
fun add(
61+
@Param(name = "priority") p: Int,
62+
@Param(name = "e") e: Int,
63+
) = queue.add(p, e)
64+
65+
@Operation
66+
fun remove(
67+
@Param(name = "priority") p: Int,
68+
@Param(name = "e") e: Int,
69+
) = queue.remove(p, e)
70+
71+
@Operation
72+
fun removeIf(@Param(name = "e") e: Int) = queue.removeIf { it == e }
73+
74+
@Operation
75+
fun removeIf(@Param(name = "priority") p: Int, @Param(name = "e") e: Int) = queue.removeIf(p) { it == e }
76+
77+
@Operation
78+
fun remove(@Param(name = "e") e: Int) = queue.remove(e)
79+
}

0 commit comments

Comments
 (0)