JetBrains / lincheck

Framework for testing concurrent data structures
Mozilla Public License 2.0
589 stars 34 forks source link

Error while adding a custom scenario #401

Open de-shyt opened 2 months ago

de-shyt commented 2 months ago

I am using blocking operations, and for this purpose I created a blockingActor method in the Lincheck library. The corresponding PR is here.

I added a custom scenario to the modelCheckingTest:

scenario {
            parallel {
                thread {
                    blockingActor(Buffered1ChannelTest::send, 2)
                    blockingActor(Buffered1ChannelTest::receive)
                    blockingActor(Buffered1ChannelTest::send, 2)
                }
                thread {
                    blockingActor(Buffered1ChannelTest::send, 2)
                }
                thread {
                    blockingActor(Buffered1ChannelTest::receive)
                }
            }
        }

The test fails with IllegalStateException:

Wow! You've caught a bug in Lincheck.
We kindly ask to provide an issue here: https://github.com/JetBrains/lincheck/issues,
attaching a stack trace printed below and the code that causes the error.

Exception stacktrace:
java.lang.IllegalStateException: Trying to switch the execution to thread 0,
but only the following threads are eligible to switch: [1]
    at org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingStrategy.chooseThread(ModelCheckingStrategy.kt:306)
    at org.jetbrains.kotlinx.lincheck.strategy.managed.ManagedStrategy.doSwitchCurrentThread(ManagedStrategy.kt:524)
    at org.jetbrains.kotlinx.lincheck.strategy.managed.ManagedStrategy.switchCurrentThread(ManagedStrategy.kt:500)
    at org.jetbrains.kotlinx.lincheck.strategy.managed.ManagedStrategy.switchCurrentThread$default(ManagedStrategy.kt:493)
    at org.jetbrains.kotlinx.lincheck.strategy.managed.ManagedStrategy.newSwitchPoint(ManagedStrategy.kt:402)
    at org.jetbrains.kotlinx.lincheck.strategy.managed.ManagedStrategy.beforeReadField(ManagedStrategy.kt:726)
    at sun.nio.ch.lincheck.Injections.beforeReadField(Injections.java:182)
    at com.deshyt.buffered.BufferedChannel.expandBuffer(BufferedChannel.kt:373)
    at com.deshyt.buffered.BufferedChannel.access$expandBuffer(BufferedChannel.kt:12)
    at com.deshyt.buffered.BufferedChannel.trySuspendRequest(BufferedChannel.kt:230)
    at com.deshyt.buffered.BufferedChannel.updateCellOnReceive(BufferedChannel.kt:163)
    at com.deshyt.buffered.BufferedChannel.receive(BufferedChannel.kt:144)
    at com.deshyt.ChannelTestBase.receive(ChannelTestBase.kt:29)
    at org.jetbrains.kotlinx.lincheck.runner.TestThreadExecution134.run(Unknown Source)
    at org.jetbrains.kotlinx.lincheck.runner.FixedActiveThreadsExecutor.testThreadRunnable$lambda$10(FixedActiveThreadsExecutor.kt:172)
    at java.base/java.lang.Thread.run(Thread.java:1583)

Check failed.
java.lang.IllegalStateException: Check failed.
    at org.jetbrains.kotlinx.lincheck.LinChecker.runReplayForPlugin(LinChecker.kt:133)
    at org.jetbrains.kotlinx.lincheck.LinChecker.checkImpl(LinChecker.kt:114)
    at org.jetbrains.kotlinx.lincheck.LinChecker.checkImpl$lincheck(LinChecker.kt:65)
    at org.jetbrains.kotlinx.lincheck.LinChecker.check(LinChecker.kt:47)
    at org.jetbrains.kotlinx.lincheck.LinChecker$Companion.check(LinChecker.kt:195)
    at org.jetbrains.kotlinx.lincheck.LinCheckerKt.check(LinChecker.kt:295)
    at org.jetbrains.kotlinx.lincheck.LinCheckerKt.check(LinChecker.kt:304)
    at com.deshyt.TestBase.modelCheckingTest(Unknown Source)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
    at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
    at java.base/java.lang.reflect.Method.invoke(Method.java:580)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:119)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:66)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

If the amount of operations in the first thread is reduced, the IllegalStateException error disappears (although other exceptions occur).

The code is stored here and can be reproduced by running Buffered1ChannelTest.

Lincheck version: 2.34 Lincheck plugin version: 0.9 Intellij IDEA version: 2024.2.2