Skip to content

Commit 16f0140

Browse files
committed
Update linearizability tests
1 parent e08fd07 commit 16f0140

File tree

5 files changed

+79
-21
lines changed

5 files changed

+79
-21
lines changed

core/kotlinx-coroutines-core/src/internal/LockFreeTaskQueue.kt

+6
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ internal open class LockFreeTaskQueue<E : Any>(
6767

6868
// Used for validation in tests only
6969
fun <R> map(transform: (E) -> R): List<R> = _cur.value.map(transform)
70+
71+
// Used for validation in tests only
72+
fun isClosed(): Boolean = _cur.value.isClosed()
7073
}
7174

7275
/**
@@ -262,6 +265,9 @@ internal class LockFreeTaskQueueCore<E : Any>(
262265
return res
263266
}
264267

268+
// Used for validation in tests only
269+
fun isClosed(): Boolean = _state.value and CLOSED_MASK != 0L
270+
265271

266272
// Instance of this class is placed into array when we have to copy array, but addLast is in progress --
267273
// it had already reserved a slot in the array (with null) and have not yet put its value there.

core/kotlinx-coroutines-core/test/linearizability/ChannelIsClosedLinearizabilityTest.kt

+19-2
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,28 @@ class ChannelIsClosedLinearizabilityTest : TestBase() {
4444
@Test
4545
fun testLinearizability() {
4646
val options = StressOptions()
47-
.iterations(100)
48-
.invocationsPerIteration(1000 * stressTestMultiplier)
47+
.iterations(100 * stressTestMultiplierSqrt)
48+
.invocationsPerIteration(1000 * stressTestMultiplierSqrt)
4949
.threads(3)
5050
.verifier(LinVerifier::class.java)
5151

5252
LinChecker.check(ChannelIsClosedLinearizabilityTest::class.java, options)
5353
}
54+
55+
override fun equals(other: Any?): Boolean {
56+
if (this === other) return true
57+
if (javaClass != other?.javaClass) return false
58+
59+
other as ChannelIsClosedLinearizabilityTest
60+
61+
if (channel != other.channel) return false
62+
63+
return true
64+
}
65+
66+
override fun hashCode(): Int {
67+
return channel.hashCode()
68+
}
69+
70+
5471
}

core/kotlinx-coroutines-core/test/linearizability/ChannelLinearizabilityTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class ChannelLinearizabilityTest : TestBase() {
7171
private fun runTest(capacity: Int) {
7272
ChannelLinearizabilityTest.capacity = capacity
7373
val options = StressOptions()
74-
.iterations(100)
75-
.invocationsPerIteration(1000 * stressTestMultiplier)
74+
.iterations(100 * stressTestMultiplierSqrt)
75+
.invocationsPerIteration(1000 * stressTestMultiplierSqrt)
7676
.threads(3)
7777
.verifier(LinVerifier::class.java)
7878
LinChecker.check(ChannelLinearizabilityTest::class.java, options)

core/kotlinx-coroutines-core/test/linearizability/LockFreeListLinearizabilityTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ class LockFreeListLinearizabilityTest : TestBase() {
4646
@Test
4747
fun testAddRemoveLinearizability() {
4848
val options = StressOptions()
49-
.iterations(100)
50-
.invocationsPerIteration(1000 * stressTestMultiplier)
49+
.iterations(100 * stressTestMultiplierSqrt)
50+
.invocationsPerIteration(1000 * stressTestMultiplierSqrt)
5151
.threads(3)
5252
LinChecker.check(LockFreeListLinearizabilityTest::class.java, options)
5353
}

core/kotlinx-coroutines-core/test/linearizability/LockFreeTaskQueueLinearizabilityTest.kt

+50-15
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,46 @@ import kotlinx.coroutines.*
1313
import kotlinx.coroutines.internal.*
1414
import kotlin.test.*
1515

16+
internal data class Snapshot(val elements: List<Int>, val isClosed: Boolean) {
17+
constructor(q: LockFreeTaskQueue<Int>) : this(q.map { it }, q.isClosed())
18+
}
19+
1620
@OpGroupConfig.OpGroupConfigs(OpGroupConfig(name = "consumer", nonParallel = true))
1721
@Param(name = "value", gen = IntGen::class, conf = "1:3")
18-
class LockFreeTaskQueueLinearizabilityTest : TestBase() {
22+
class LockFreeTaskQueueLinearizabilityTestSC : LockFreeTaskQueueLinearizabilityTestBase() {
23+
private val q: LockFreeTaskQueue<Int> = LockFreeTaskQueue(singleConsumer = true)
24+
25+
@Operation
26+
fun close() = q.close()
27+
28+
@Operation
29+
fun addLast(@Param(name = "value") value: Int) = q.addLast(value)
1930

20-
private companion object {
21-
var singleConsumer = false
31+
/**
32+
* Note, that removeFirstOrNull is not linearizable w.r.t. to addLast, so here
33+
* we test only linearizability of close.
34+
*/
35+
// @Operation(group = "consumer")
36+
// fun removeFirstOrNull() = q.removeFirstOrNull()
37+
38+
@Test
39+
fun testSC() = linTest()
40+
41+
override fun equals(other: Any?): Boolean {
42+
if (this === other) return true
43+
if (javaClass != other?.javaClass) return false
44+
45+
other as LockFreeTaskQueueLinearizabilityTestSC
46+
47+
return Snapshot(q) == Snapshot(other.q)
2248
}
2349

24-
private val q: LockFreeTaskQueue<Int> = LockFreeTaskQueue(singleConsumer)
50+
override fun hashCode(): Int = Snapshot(q).hashCode()
51+
}
52+
53+
@Param(name = "value", gen = IntGen::class, conf = "1:3")
54+
class LockFreeTaskQueueLinearizabilityTestMC : LockFreeTaskQueueLinearizabilityTestBase() {
55+
private val q: LockFreeTaskQueue<Int> = LockFreeTaskQueue(singleConsumer = false)
2556

2657
@Operation
2758
fun close() = q.close()
@@ -37,22 +68,26 @@ class LockFreeTaskQueueLinearizabilityTest : TestBase() {
3768
// fun removeFirstOrNull() = q.removeFirstOrNull()
3869

3970
@Test
40-
fun testLinearizabilitySC() {
41-
singleConsumer = true
42-
linTest()
43-
}
71+
fun testMC() = linTest()
4472

45-
@Test
46-
fun testLinearizabilityMC() {
47-
singleConsumer = false
48-
linTest()
73+
override fun equals(other: Any?): Boolean {
74+
if (this === other) return true
75+
if (javaClass != other?.javaClass) return false
76+
77+
other as LockFreeTaskQueueLinearizabilityTestMC
78+
79+
return Snapshot(q) == Snapshot(other.q)
4980
}
5081

51-
private fun linTest() {
82+
override fun hashCode(): Int = Snapshot(q).hashCode()
83+
}
84+
85+
open class LockFreeTaskQueueLinearizabilityTestBase : TestBase() {
86+
fun linTest() {
5287
val options = StressOptions()
5388
.iterations(100 * stressTestMultiplierSqrt)
5489
.invocationsPerIteration(1000 * stressTestMultiplierSqrt)
55-
.threads(3)
56-
LinChecker.check(LockFreeTaskQueueLinearizabilityTest::class.java, options)
90+
.threads(2)
91+
LinChecker.check(this::class.java, options)
5792
}
5893
}

0 commit comments

Comments
 (0)