diff --git a/.gitignore b/.gitignore
index aed7103292..52843ca5b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,7 @@
!/.idea/copyright
!/.idea/codeStyleSettings.xml
!/.idea/codeStyles
+!/.idea/dictionaries
*.iml
.gradle
.gradletasknamecache
diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml
new file mode 100644
index 0000000000..3da8e22952
--- /dev/null
+++ b/.idea/dictionaries/shared.xml
@@ -0,0 +1,9 @@
+
+
+
+ kotlinx
+ lincheck
+ redirector
+
+
+
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 1ffa02d1ae..0207be9e6e 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -12,7 +12,7 @@ junit_version=4.12
atomicfu_version=0.14.4
knit_version=0.2.2
html_version=0.6.8
-lincheck_version=2.7.1
+lincheck_version=2.10
dokka_version=0.9.16-rdev-2-mpp-hacks
byte_buddy_version=1.10.9
reactor_version=3.2.5.RELEASE
diff --git a/kotlinx-coroutines-core/build.gradle b/kotlinx-coroutines-core/build.gradle
index 314eea350b..da9cdb4994 100644
--- a/kotlinx-coroutines-core/build.gradle
+++ b/kotlinx-coroutines-core/build.gradle
@@ -184,13 +184,22 @@ jvmTest {
minHeapSize = '1g'
maxHeapSize = '1g'
enableAssertions = true
- systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager'
+ if (!Idea.active) {
+ // We should not set this security manager when `jvmTest`
+ // is invoked by IntelliJ IDEA since we need to pass
+ // system properties for Lincheck and stress tests.
+ // TODO Remove once IDEA is smart enough to select between `jvmTest`/`jvmStressTest`/`jvmLincheckTest` #KTIJ-599
+ systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager'
+ }
// 'stress' is required to be able to run all subpackage tests like ":jvmTests --tests "*channels*" -Pstress=true"
if (!Idea.active && rootProject.properties['stress'] == null) {
+ exclude '**/*LincheckTest.*'
exclude '**/*StressTest.*'
}
- systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test
-
+ if (Idea.active) {
+ // Configure the IDEA runner for Lincheck
+ configureJvmForLincheck(jvmTest)
+ }
// TODO: JVM IR generates different stacktrace so temporary disable stacktrace tests
if (rootProject.ext.jvm_ir_enabled) {
filter {
@@ -219,23 +228,41 @@ task jvmStressTest(type: Test, dependsOn: compileTestKotlinJvm) {
systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '10'
}
+task jvmLincheckTest(type: Test, dependsOn: compileTestKotlinJvm) {
+ classpath = files { jvmTest.classpath }
+ testClassesDirs = files { jvmTest.testClassesDirs }
+ include '**/*LincheckTest.*'
+ enableAssertions = true
+ testLogging.showStandardStreams = true
+ configureJvmForLincheck(jvmLincheckTest)
+}
+
+static void configureJvmForLincheck(task) {
+ task.minHeapSize = '1g'
+ task.maxHeapSize = '6g' // we may need more space for building an interleaving tree in the model checking mode
+ task.jvmArgs = ['--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED', // required for transformation
+ '--add-exports', 'java.base/jdk.internal.util=ALL-UNNAMED'] // in the model checking mode
+ task.systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '2'
+ task.systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '1' // better for the model checking mode
+}
+
task jdk16Test(type: Test, dependsOn: [compileTestKotlinJvm, checkJdk16]) {
classpath = files { jvmTest.classpath }
testClassesDirs = files { jvmTest.testClassesDirs }
executable = "$System.env.JDK_16/bin/java"
exclude '**/*LFStressTest.*' // lock-freedom tests use LockFreedomTestEnvironment which needs JDK8
- exclude '**/*LCStressTest.*' // lin-check tests use LinChecker which needs JDK8
+ exclude '**/*LincheckTest.*' // Lincheck tests use LinChecker which needs JDK8
exclude '**/exceptions/**' // exceptions tests check suppressed exception which needs JDK8
exclude '**/ExceptionsGuideTest.*'
exclude '**/RunInterruptibleStressTest.*' // fails on JDK 1.6 due to JDK bug
}
-// Run these tests only during nightly stress test
+// Run jdk16Test test only during nightly stress test
jdk16Test.onlyIf { project.properties['stressTest'] != null }
-// Always run those tests
-task moreTest(dependsOn: [jvmStressTest, jdk16Test])
-build.dependsOn moreTest
+// Always check additional test sets
+task moreTest(dependsOn: [jvmStressTest, jvmLincheckTest, jdk16Test])
+check.dependsOn moreTest
task testsJar(type: Jar, dependsOn: jvmTestClasses) {
classifier = 'tests'
diff --git a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt
index cdb1b78882..a056ef08ed 100644
--- a/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt
+++ b/kotlinx-coroutines-core/common/src/CancellableContinuationImpl.kt
@@ -85,6 +85,13 @@ internal open class CancellableContinuationImpl(
public override val isCancelled: Boolean get() = state is CancelledContinuation
+ // We cannot invoke `state.toString()` since it may cause a circular dependency
+ private val stateDebugRepresentation get() = when(state) {
+ is NotCompleted -> "Active"
+ is CancelledContinuation -> "Cancelled"
+ else -> "Completed"
+ }
+
public override fun initCancellability() {
setupCancellation()
}
@@ -503,7 +510,7 @@ internal open class CancellableContinuationImpl(
// For nicer debugging
public override fun toString(): String =
- "${nameString()}(${delegate.toDebugString()}){$state}@$hexAddress"
+ "${nameString()}(${delegate.toDebugString()}){$stateDebugRepresentation}@$hexAddress"
protected open fun nameString(): String =
"CancellableContinuation"
diff --git a/kotlinx-coroutines-core/common/src/internal/Symbol.kt b/kotlinx-coroutines-core/common/src/internal/Symbol.kt
index 4fa8f540af..cd25d3c1af 100644
--- a/kotlinx-coroutines-core/common/src/internal/Symbol.kt
+++ b/kotlinx-coroutines-core/common/src/internal/Symbol.kt
@@ -10,7 +10,7 @@ package kotlinx.coroutines.internal
* @suppress **This is unstable API and it is subject to change.**
*/
internal class Symbol(val symbol: String) {
- override fun toString(): String = symbol
+ override fun toString(): String = "<$symbol>"
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
inline fun unbox(value: Any?): T = if (value === this) null as T else value as T
diff --git a/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt
new file mode 100644
index 0000000000..5ba7acf994
--- /dev/null
+++ b/kotlinx-coroutines-core/jvm/test/AbstractLincheckTest.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+package kotlinx.coroutines
+
+import org.jetbrains.kotlinx.lincheck.*
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
+import org.jetbrains.kotlinx.lincheck.strategy.stress.*
+import org.jetbrains.kotlinx.lincheck.verifier.*
+import org.junit.*
+
+abstract class AbstractLincheckTest : VerifierState() {
+ open fun > O.customize(isStressTest: Boolean): O = this
+ open fun ModelCheckingOptions.customize(isStressTest: Boolean): ModelCheckingOptions = this
+ open fun StressOptions.customize(isStressTest: Boolean): StressOptions = this
+
+ @Test
+ fun modelCheckingTest() = ModelCheckingOptions()
+ .iterations(if (isStressTest) 100 else 20)
+ .invocationsPerIteration(if (isStressTest) 10_000 else 1_000)
+ .commonConfiguration()
+ .customize(isStressTest)
+ .check(this::class)
+
+ @Test
+ fun stressTest() = StressOptions()
+ .iterations(if (isStressTest) 100 else 20)
+ .invocationsPerIteration(if (isStressTest) 10_000 else 1_000)
+ .commonConfiguration()
+ .customize(isStressTest)
+ .check(this::class)
+
+ private fun > O.commonConfiguration(): O = this
+ .actorsBefore(if (isStressTest) 3 else 1)
+ .threads(3)
+ .actorsPerThread(if (isStressTest) 4 else 2)
+ .actorsAfter(if (isStressTest) 3 else 0)
+ .customize(isStressTest)
+
+ override fun extractState(): Any = error("Not implemented")
+}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt b/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt
deleted file mode 100644
index 62ded9f969..0000000000
--- a/kotlinx-coroutines-core/jvm/test/LCStressOptionsDefault.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright 2016-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-package kotlinx.coroutines
-
-import org.jetbrains.kotlinx.lincheck.*
-import org.jetbrains.kotlinx.lincheck.strategy.stress.*
-import kotlin.reflect.*
-
-class LCStressOptionsDefault : StressOptions() {
- init {
- iterations(100 * stressTestMultiplierCbrt)
- invocationsPerIteration(1000 * stressTestMultiplierCbrt)
- actorsBefore(if (isStressTest) 3 else 0)
- threads(3)
- actorsPerThread(if (isStressTest) 3 else 2)
- }
-}
-
-fun Options<*,*>.check(testClass: KClass<*>) = LinChecker.check(testClass.java, this)
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt
similarity index 88%
rename from kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt
rename to kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt
index 8836fdc7be..fbd5c0d8f3 100644
--- a/kotlinx-coroutines-core/jvm/test/linearizability/ChannelsLCStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt
@@ -3,7 +3,7 @@
*/
@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
+package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
@@ -11,37 +11,37 @@ import kotlinx.coroutines.channels.Channel.Factory.CONFLATED
import kotlinx.coroutines.channels.Channel.Factory.RENDEZVOUS
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.selects.*
+import org.jetbrains.kotlinx.lincheck.*
import org.jetbrains.kotlinx.lincheck.annotations.*
import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.paramgen.*
import org.jetbrains.kotlinx.lincheck.verifier.*
-import org.junit.*
-class RendezvousChannelLCStressTest : ChannelLCStressTestBase(
+class RendezvousChannelLincheckTest : ChannelLincheckTestBase(
c = Channel(RENDEZVOUS),
sequentialSpecification = SequentialRendezvousChannel::class.java
)
class SequentialRendezvousChannel : SequentialIntChannelBase(RENDEZVOUS)
-class Array1ChannelLCStressTest : ChannelLCStressTestBase(
+class Array1ChannelLincheckTest : ChannelLincheckTestBase(
c = Channel(1),
sequentialSpecification = SequentialArray1RendezvousChannel::class.java
)
class SequentialArray1RendezvousChannel : SequentialIntChannelBase(1)
-class Array2ChannelLCStressTest : ChannelLCStressTestBase(
+class Array2ChannelLincheckTest : ChannelLincheckTestBase(
c = Channel(2),
sequentialSpecification = SequentialArray2RendezvousChannel::class.java
)
class SequentialArray2RendezvousChannel : SequentialIntChannelBase(2)
-class UnlimitedChannelLCStressTest : ChannelLCStressTestBase(
+class UnlimitedChannelLincheckTest : ChannelLincheckTestBase(
c = Channel(UNLIMITED),
sequentialSpecification = SequentialUnlimitedChannel::class.java
)
class SequentialUnlimitedChannel : SequentialIntChannelBase(UNLIMITED)
-class ConflatedChannelLCStressTest : ChannelLCStressTestBase(
+class ConflatedChannelLincheckTest : ChannelLincheckTestBase(
c = Channel(CONFLATED),
sequentialSpecification = SequentialConflatedChannel::class.java
)
@@ -51,8 +51,11 @@ class SequentialConflatedChannel : SequentialIntChannelBase(CONFLATED)
Param(name = "value", gen = IntGen::class, conf = "1:5"),
Param(name = "closeToken", gen = IntGen::class, conf = "1:3")
)
-abstract class ChannelLCStressTestBase(private val c: Channel, private val sequentialSpecification: Class<*>) {
- @Operation
+abstract class ChannelLincheckTestBase(
+ private val c: Channel,
+ private val sequentialSpecification: Class<*>
+) : AbstractLincheckTest() {
+ @Operation(promptCancellation = true)
suspend fun send(@Param(name = "value") value: Int): Any = try {
c.send(value)
} catch (e: NumberedCancellationException) {
@@ -74,7 +77,7 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val
e.testResult
}
- @Operation
+ @Operation(promptCancellation = true)
suspend fun receive(): Any = try {
c.receive()
} catch (e: NumberedCancellationException) {
@@ -96,7 +99,7 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val
e.testResult
}
- @Operation
+ @Operation(causesBlocking = true)
fun close(@Param(name = "closeToken") token: Int): Boolean = c.close(NumberedCancellationException(token))
// TODO: this operation should be (and can be!) linearizable, but is not
@@ -113,11 +116,8 @@ abstract class ChannelLCStressTestBase(private val c: Channel, private val
// @Operation
fun isEmpty() = c.isEmpty
- @Test
- fun test() = LCStressOptionsDefault()
- .actorsBefore(0)
- .sequentialSpecification(sequentialSpecification)
- .check(this::class)
+ override fun > O.customize(isStressTest: Boolean): O =
+ actorsBefore(0).sequentialSpecification(sequentialSpecification)
}
private class NumberedCancellationException(number: Int) : CancellationException() {
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeListLincheckTest.kt
similarity index 83%
rename from kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt
rename to kotlinx-coroutines-core/jvm/test/lincheck/LockFreeListLincheckTest.kt
index 5f91c640a6..4f1bb6ad02 100644
--- a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeListLCStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeListLincheckTest.kt
@@ -3,18 +3,17 @@
*/
@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
+package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import org.jetbrains.kotlinx.lincheck.annotations.*
import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.paramgen.*
-import org.jetbrains.kotlinx.lincheck.verifier.*
-import kotlin.test.*
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
@Param(name = "value", gen = IntGen::class, conf = "1:5")
-class LockFreeListLCStressTest : VerifierState() {
+class LockFreeListLincheckTest : AbstractLincheckTest() {
class Node(val value: Int): LockFreeLinkedListNode()
private val q: LockFreeLinkedListHead = LockFreeLinkedListHead()
@@ -43,12 +42,12 @@ class LockFreeListLCStressTest : VerifierState() {
private fun Any.isSame(value: Int) = this is Node && this.value == value
- @Test
- fun testAddRemoveLinearizability() = LCStressOptionsDefault().check(this::class)
-
override fun extractState(): Any {
val elements = ArrayList()
q.forEach { elements.add(it.value) }
return elements
}
+
+ override fun ModelCheckingOptions.customize(isStressTest: Boolean) =
+ checkObstructionFreedom()
}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt
similarity index 50%
rename from kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt
rename to kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt
index de494cc1e6..2a9164e1d7 100644
--- a/kotlinx-coroutines-core/jvm/test/linearizability/LockFreeTaskQueueLCStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/LockFreeTaskQueueLincheckTest.kt
@@ -3,19 +3,21 @@
*/
@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
+package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
+import org.jetbrains.kotlinx.lincheck.*
import org.jetbrains.kotlinx.lincheck.annotations.*
import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.paramgen.*
-import org.jetbrains.kotlinx.lincheck.verifier.*
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
import org.jetbrains.kotlinx.lincheck.verifier.quiescent.*
-import kotlin.test.*
@Param(name = "value", gen = IntGen::class, conf = "1:3")
-internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLCStressTest protected constructor(singleConsumer: Boolean) : VerifierState() {
+internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLincheckTest(
+ val singleConsumer: Boolean
+) : AbstractLincheckTest() {
@JvmField
protected val q = LockFreeTaskQueue(singleConsumer = singleConsumer)
@@ -25,20 +27,24 @@ internal abstract class AbstractLockFreeTaskQueueWithoutRemoveLCStressTest prote
@Operation
fun addLast(@Param(name = "value") value: Int) = q.addLast(value)
- @QuiescentConsistent
- @Operation(group = "consumer")
- fun removeFirstOrNull() = q.removeFirstOrNull()
+ override fun > O.customize(isStressTest: Boolean): O =
+ verifier(QuiescentConsistencyVerifier::class.java)
override fun extractState() = q.map { it } to q.isClosed()
- @Test
- fun testWithRemoveForQuiescentConsistency() = LCStressOptionsDefault()
- .verifier(QuiescentConsistencyVerifier::class.java)
- .check(this::class)
+ override fun ModelCheckingOptions.customize(isStressTest: Boolean) =
+ checkObstructionFreedom()
}
-@OpGroupConfig(name = "consumer", nonParallel = false)
-internal class MCLockFreeTaskQueueWithRemoveLCStressTest : AbstractLockFreeTaskQueueWithoutRemoveLCStressTest(singleConsumer = false)
+internal class MCLockFreeTaskQueueWithRemoveLincheckTest : AbstractLockFreeTaskQueueWithoutRemoveLincheckTest(singleConsumer = false) {
+ @QuiescentConsistent
+ @Operation(blocking = true)
+ fun removeFirstOrNull() = q.removeFirstOrNull()
+}
@OpGroupConfig(name = "consumer", nonParallel = true)
-internal class SCLockFreeTaskQueueWithRemoveLCStressTest : AbstractLockFreeTaskQueueWithoutRemoveLCStressTest(singleConsumer = true)
\ No newline at end of file
+internal class SCLockFreeTaskQueueWithRemoveLincheckTest : AbstractLockFreeTaskQueueWithoutRemoveLincheckTest(singleConsumer = true) {
+ @QuiescentConsistent
+ @Operation(group = "consumer")
+ fun removeFirstOrNull() = q.removeFirstOrNull()
+}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/MutexLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt
similarity index 54%
rename from kotlinx-coroutines-core/jvm/test/linearizability/MutexLCStressTest.kt
rename to kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt
index 9542b5d8de..6e350660ae 100644
--- a/kotlinx-coroutines-core/jvm/test/linearizability/MutexLCStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt
@@ -2,30 +2,31 @@
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
+package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.*
+import org.jetbrains.kotlinx.lincheck.*
import org.jetbrains.kotlinx.lincheck.annotations.Operation
-import org.jetbrains.kotlinx.lincheck.verifier.*
-import org.junit.*
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
-class MutexLCStressTest : VerifierState() {
+class MutexLincheckTest : AbstractLincheckTest() {
private val mutex = Mutex()
@Operation
fun tryLock() = mutex.tryLock()
- @Operation
+ @Operation(promptCancellation = true)
suspend fun lock() = mutex.lock()
@Operation(handleExceptionsAsResult = [IllegalStateException::class])
fun unlock() = mutex.unlock()
- @Test
- fun test() = LCStressOptionsDefault()
- .actorsBefore(0)
- .check(this::class)
+ override fun > O.customize(isStressTest: Boolean): O =
+ actorsBefore(0)
+
+ override fun ModelCheckingOptions.customize(isStressTest: Boolean) =
+ checkObstructionFreedom()
override fun extractState() = mutex.isLocked
}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentListRemoveLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentListRemoveLincheckTest.kt
similarity index 66%
rename from kotlinx-coroutines-core/jvm/test/linearizability/SegmentListRemoveLCStressTest.kt
rename to kotlinx-coroutines-core/jvm/test/lincheck/SegmentListRemoveLincheckTest.kt
index 5daed99829..5a8d7b475d 100644
--- a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentListRemoveLCStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentListRemoveLincheckTest.kt
@@ -4,18 +4,16 @@
@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
+package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
+import org.jetbrains.kotlinx.lincheck.*
import org.jetbrains.kotlinx.lincheck.annotations.*
-import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.paramgen.*
-import org.jetbrains.kotlinx.lincheck.verifier.*
-import org.junit.*
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
-
-class SegmentListRemoveLCStressTest : VerifierState() {
+class SegmentListRemoveLincheckTest : AbstractLincheckTest() {
private val q = SegmentBasedQueue()
private val segments: Array>
@@ -29,6 +27,9 @@ class SegmentListRemoveLCStressTest : VerifierState() {
segments[index].removeSegment()
}
+ override fun > O.customize(isStressTest: Boolean): O = this
+ .actorsBefore(0).actorsAfter(0)
+
override fun extractState() = segments.map { it.logicallyRemoved }
@Validate
@@ -37,9 +38,6 @@ class SegmentListRemoveLCStressTest : VerifierState() {
q.checkAllSegmentsAreNotLogicallyRemoved()
}
- @Test
- fun test() = LCStressOptionsDefault()
- .actorsBefore(0)
- .actorsAfter(0)
- .check(this::class)
+ override fun ModelCheckingOptions.customize(isStressTest: Boolean) =
+ checkObstructionFreedom()
}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentQueueLincheckTest.kt
similarity index 78%
rename from kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt
rename to kotlinx-coroutines-core/jvm/test/lincheck/SegmentQueueLincheckTest.kt
index 89bf8dfaa4..76a59e39e7 100644
--- a/kotlinx-coroutines-core/jvm/test/linearizability/SegmentQueueLCStressTest.kt
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/SegmentQueueLincheckTest.kt
@@ -3,18 +3,17 @@
*/
@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
+package kotlinx.coroutines.lincheck
import kotlinx.coroutines.*
import kotlinx.coroutines.internal.SegmentBasedQueue
import org.jetbrains.kotlinx.lincheck.annotations.*
import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.paramgen.*
-import org.jetbrains.kotlinx.lincheck.verifier.*
-import org.junit.*
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
@Param(name = "value", gen = IntGen::class, conf = "1:5")
-class SegmentQueueLCStressTest : VerifierState() {
+class SegmentQueueLincheckTest : AbstractLincheckTest() {
private val q = SegmentBasedQueue()
@Operation
@@ -40,6 +39,6 @@ class SegmentQueueLCStressTest : VerifierState() {
return elements to closed
}
- @Test
- fun test() = LCStressOptionsDefault().check(this::class)
+ override fun ModelCheckingOptions.customize(isStressTest: Boolean) =
+ checkObstructionFreedom()
}
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt b/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt
new file mode 100644
index 0000000000..84ce773c15
--- /dev/null
+++ b/kotlinx-coroutines-core/jvm/test/lincheck/SemaphoreLincheckTest.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+@file:Suppress("unused")
+package kotlinx.coroutines.lincheck
+
+import kotlinx.coroutines.*
+import kotlinx.coroutines.sync.*
+import org.jetbrains.kotlinx.lincheck.*
+import org.jetbrains.kotlinx.lincheck.annotations.Operation
+import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.*
+
+abstract class SemaphoreLincheckTestBase(permits: Int) : AbstractLincheckTest() {
+ private val semaphore = Semaphore(permits)
+
+ @Operation
+ fun tryAcquire() = semaphore.tryAcquire()
+
+ @Operation(promptCancellation = true)
+ suspend fun acquire() = semaphore.acquire()
+
+ @Operation(handleExceptionsAsResult = [IllegalStateException::class])
+ fun release() = semaphore.release()
+
+ override fun > O.customize(isStressTest: Boolean): O =
+ actorsBefore(0)
+
+ override fun extractState() = semaphore.availablePermits
+
+ override fun ModelCheckingOptions.customize(isStressTest: Boolean) =
+ checkObstructionFreedom()
+}
+
+class Semaphore1LincheckTest : SemaphoreLincheckTestBase(1)
+class Semaphore2LincheckTest : SemaphoreLincheckTestBase(2)
\ No newline at end of file
diff --git a/kotlinx-coroutines-core/jvm/test/linearizability/SemaphoreLCStressTest.kt b/kotlinx-coroutines-core/jvm/test/linearizability/SemaphoreLCStressTest.kt
deleted file mode 100644
index 52902f4987..0000000000
--- a/kotlinx-coroutines-core/jvm/test/linearizability/SemaphoreLCStressTest.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-@file:Suppress("unused")
-package kotlinx.coroutines.linearizability
-
-import kotlinx.coroutines.*
-import kotlinx.coroutines.sync.*
-import org.jetbrains.kotlinx.lincheck.annotations.Operation
-import org.jetbrains.kotlinx.lincheck.verifier.*
-import org.junit.*
-
-abstract class SemaphoreLCStressTestBase(permits: Int) : VerifierState() {
- private val semaphore = Semaphore(permits)
-
- @Operation
- fun tryAcquire() = semaphore.tryAcquire()
-
- @Operation
- suspend fun acquire() = semaphore.acquire()
-
- @Operation(handleExceptionsAsResult = [IllegalStateException::class])
- fun release() = semaphore.release()
-
- @Test
- fun test() = LCStressOptionsDefault()
- .actorsBefore(0)
- .check(this::class)
-
- override fun extractState() = semaphore.availablePermits
-}
-
-class Semaphore1LCStressTest : SemaphoreLCStressTestBase(1)
-class Semaphore2LCStressTest : SemaphoreLCStressTestBase(2)
\ No newline at end of file