Skip to content

Commit

Permalink
Run failure output test checks under Lincheck java-agent
Browse files Browse the repository at this point in the history
Signed-off-by: Evgeniy Moiseenko <[email protected]>
  • Loading branch information
eupp committed May 20, 2024
1 parent f4533c6 commit 200e12e
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 18 deletions.
46 changes: 42 additions & 4 deletions src/jvm/main/org/jetbrains/kotlinx/lincheck/LinChecker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,18 +47,26 @@ class LinChecker (private val testClass: Class<*>, options: Options<*, *>?) {
}

/**
* @return TestReport with information about concurrent test run.
* Runs Lincheck to check the tested class under given configurations.
*
* @param cont Optional continuation taking [LincheckFailure] as an argument.
* The continuation is run in the context when Lincheck java-agent is still attached.
* @return [LincheckFailure] if a failure is discovered, null otherwise.
*/
@Synchronized // never run Lincheck tests in parallel
internal fun checkImpl(): LincheckFailure? {
internal fun checkImpl(cont: LincheckFailureContinuation? = null): LincheckFailure? {
check(testConfigurations.isNotEmpty()) { "No Lincheck test configuration to run" }
lincheckVerificationStarted()
for (testCfg in testConfigurations) {
withLincheckJavaAgent(testCfg.instrumentationMode) {
val failure = testCfg.checkImpl()
if (failure != null) return failure
if (failure != null) {
if (cont != null) cont(failure)
return failure
}
}
}
if (cont != null) cont(null)
return null
}

Expand Down Expand Up @@ -203,6 +211,36 @@ fun <O : Options<O, *>> O.check(testClass: Class<*>) = LinChecker.check(testClas
*/
fun <O : Options<O, *>> O.check(testClass: KClass<*>) = this.check(testClass.java)

internal fun <O : Options<O, *>> O.checkImpl(testClass: Class<*>) = LinChecker(testClass, this).checkImpl()
/**
* Runs Lincheck to check the tested class under given configurations.
*
* @param testClass Tested class.
* @return [LincheckFailure] if a failure is discovered, null otherwise.
*/
internal fun <O : Options<O, *>> O.checkImpl(testClass: Class<*>): LincheckFailure? =
LinChecker(testClass, this).checkImpl()

/**
* Runs Lincheck to check the tested class under given configurations.
*
* Takes the [LincheckFailureContinuation] as an argument.
* This is required due to current limitations of our testing infrastructure.
* Some tests need to inspect the internals of the failure object
* (for example, the stack traces of exceptions thrown during the execution).
* However, because Lincheck dynamically installs java-agent and then uninstalls it,
* this process can invalidate some internal state of the failure object
* (for example, the source code mapping information in the stack traces is typically lost).
* To overcome this problem, we run the continuation in the context when Lincheck java-agent is still attached.
*
* @param testClass Tested class.
* @param cont Continuation taking [LincheckFailure] as an argument.
* The continuation is run in the context when Lincheck java-agent is still attached.
* @return [LincheckFailure] if a failure is discovered, null otherwise.
*/
internal fun <O : Options<O, *>> O.checkImpl(testClass: Class<*>, cont: LincheckFailureContinuation) {
LinChecker(testClass, this).checkImpl(cont)
}

internal typealias LincheckFailureContinuation = (LincheckFailure?) -> Unit

internal const val NO_OPERATION_ERROR_MESSAGE = "You must specify at least one operation to test. Please refer to the user guide: https://kotlinlang.org/docs/introduction.html"
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class ClocksWithExceptionsInOutputTest {
actorsPerThread(2)
minimizeFailedScenario(false)
}
.checkImpl(this::class.java)
.checkLincheckOutput("clocks_and_exceptions.txt")
.checkImpl(this::class.java) { failure ->
failure.checkLincheckOutput("clocks_and_exceptions.txt")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ExceptionsInOutputTest {
fun `should add stackTrace to output`() = ModelCheckingOptions().apply {
actorsBefore(2)
}
.checkImpl(this::class.java)
.checkLincheckOutput("exceptions_in_output.txt")

.checkImpl(this::class.java) { failure ->
failure.checkLincheckOutput("exceptions_in_output.txt")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class InterleavingAnalysisPresentInSpinCycleFirstIterationTest {
thread { actor(InterleavingAnalysisPresentInSpinCycleFirstIterationTest::spinLock) }
}
}
.checkImpl(this::class.java)
.checkLincheckOutput("switch_in_the_middle_of_spin_cycle_causes_error.txt")
.checkImpl(this::class.java) { failure ->
failure.checkLincheckOutput("switch_in_the_middle_of_spin_cycle_causes_error.txt")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class InternalLincheckBugTest {
@Test
fun test() = ModelCheckingOptions()
.actorsPerThread(2)
.checkImpl(this::class.java)
.checkLincheckOutput("internal_bug_report.txt")
.checkImpl(this::class.java) { failure ->
failure.checkLincheckOutput("internal_bug_report.txt")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class TraceReportingTest {

@Test
fun testEmptyTrace() {
val failure = ModelCheckingOptions()
ModelCheckingOptions()
.iterations(0)
.addCustomScenario {
parallel {
Expand All @@ -135,8 +135,9 @@ class TraceReportingTest {
}
}
.sequentialSpecification(EmptySequentialImplementation::class.java)
.checkImpl(this::class.java)
failure.checkLincheckOutput("trace_reporting_empty.txt")
.checkImpl(this::class.java) { failure ->
failure.checkLincheckOutput("trace_reporting_empty.txt")
}
}

class EmptySequentialImplementation {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ class ValidationFunctionCallTest {
}
}
}
.checkImpl(this::class.java)
.checkLincheckOutput("validation_function_failure.txt")
.checkImpl(this::class.java) { failure ->
failure.checkLincheckOutput("validation_function_failure.txt")
}

}

Expand Down

0 comments on commit 200e12e

Please sign in to comment.