From e6fbc8f88ddbb0288fb6088e36a8190d92078486 Mon Sep 17 00:00:00 2001 From: Denis Lochmelis Date: Sun, 4 Aug 2024 20:26:46 +0200 Subject: [PATCH] Fix jcstress result not parsing default outcome (add parseOutcome() to LitmusAutoOutcome) --- .../autooutcomes/BooleanAutoOutcomes.kt | 10 ++++++++- .../litmuskt/autooutcomes/IntAutoOutcomes.kt | 16 ++++++++++++++ .../autooutcomes/LitmusAutoOutcome.kt | 1 + .../litmuskt/autooutcomes/LongAutoOutcomes.kt | 16 ++++++++++++++ .../kotlin/org/jetbrains/litmuskt/Codegen.kt | 21 +++++++++++-------- .../org/jetbrains/litmuskt/JCStressRunner.kt | 7 +++---- 6 files changed, 57 insertions(+), 14 deletions(-) diff --git a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/BooleanAutoOutcomes.kt b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/BooleanAutoOutcomes.kt index 4f1f83f..3ba985c 100644 --- a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/BooleanAutoOutcomes.kt +++ b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/BooleanAutoOutcomes.kt @@ -2,7 +2,11 @@ package org.jetbrains.litmuskt.autooutcomes import org.jetbrains.litmuskt.LitmusOutcomeSpecScope -// TODO +/** + * "Z" is the name for Boolean outcomes in JCStress. + */ + +// TODO: codegen open class LitmusZZOutcome( var r1: Boolean = false, @@ -16,6 +20,10 @@ open class LitmusZZOutcome( } final override fun toList() = listOf(r1, r2) + final override fun parseOutcome(str: String): LitmusZZOutcome { + val rs = str.split(", ").map(String::toBooleanStrict) + return LitmusZZOutcome(rs[0], rs[1]) + } } fun LitmusOutcomeSpecScope.accept(r1: Boolean, r2: Boolean) = diff --git a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/IntAutoOutcomes.kt b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/IntAutoOutcomes.kt index 9ecd149..2eda0e8 100644 --- a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/IntAutoOutcomes.kt +++ b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/IntAutoOutcomes.kt @@ -13,6 +13,10 @@ open class LitmusIOutcome( } final override fun toList() = listOf(r1) + final override fun parseOutcome(str: String): LitmusIOutcome { + val rs = str.split(", ").map(String::toInt) + return LitmusIOutcome(rs[0]) + } } fun LitmusOutcomeSpecScope.accept(r1: Int) = @@ -36,6 +40,10 @@ open class LitmusIIOutcome( } final override fun toList() = listOf(r1, r2) + final override fun parseOutcome(str: String): LitmusIIOutcome { + val rs = str.split(", ").map(String::toInt) + return LitmusIIOutcome(rs[0], rs[1]) + } } fun LitmusOutcomeSpecScope.accept(r1: Int, r2: Int) = @@ -60,6 +68,10 @@ open class LitmusIIIOutcome( } final override fun toList() = listOf(r1, r2, r3) + final override fun parseOutcome(str: String): LitmusIIIOutcome { + val rs = str.split(", ").map(String::toInt) + return LitmusIIIOutcome(rs[0], rs[1], rs[2]) + } } fun LitmusOutcomeSpecScope.accept(r1: Int, r2: Int, r3: Int) = @@ -85,6 +97,10 @@ open class LitmusIIIIOutcome( } final override fun toList() = listOf(r1, r2, r3, r4) + final override fun parseOutcome(str: String): LitmusIIIIOutcome { + val rs = str.split(", ").map(String::toInt) + return LitmusIIIIOutcome(rs[0], rs[1], rs[2], rs[3]) + } } fun LitmusOutcomeSpecScope.accept(r1: Int, r2: Int, r3: Int, r4: Int) = diff --git a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LitmusAutoOutcome.kt b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LitmusAutoOutcome.kt index ce26e27..0b10855 100644 --- a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LitmusAutoOutcome.kt +++ b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LitmusAutoOutcome.kt @@ -25,5 +25,6 @@ sealed interface LitmusAutoOutcome { // for JCStress interop fun toList(): List + fun parseOutcome(str: String): LitmusAutoOutcome } diff --git a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LongAutoOutcomes.kt b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LongAutoOutcomes.kt index 4d5e759..fb1e7ac 100644 --- a/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LongAutoOutcomes.kt +++ b/core/src/commonMain/kotlin/org/jetbrains/litmuskt/autooutcomes/LongAutoOutcomes.kt @@ -13,6 +13,10 @@ open class LitmusLOutcome( } final override fun toList() = listOf(r1) + final override fun parseOutcome(str: String): LitmusLOutcome { + val rs = str.split(", ").map(String::toLong) + return LitmusLOutcome(rs[0]) + } } fun LitmusOutcomeSpecScope.accept(r1: Long) = @@ -36,6 +40,10 @@ open class LitmusLLOutcome( } final override fun toList() = listOf(r1, r2) + final override fun parseOutcome(str: String): LitmusLLOutcome { + val rs = str.split(", ").map(String::toLong) + return LitmusLLOutcome(rs[0], rs[1]) + } } fun LitmusOutcomeSpecScope.accept(r1: Long, r2: Long) = @@ -60,6 +68,10 @@ open class LitmusLLLOutcome( } final override fun toList() = listOf(r1, r2, r3) + final override fun parseOutcome(str: String): LitmusLLLOutcome { + val rs = str.split(", ").map(String::toLong) + return LitmusLLLOutcome(rs[0], rs[1], rs[2]) + } } fun LitmusOutcomeSpecScope.accept(r1: Long, r2: Long, r3: Long) = @@ -85,6 +97,10 @@ open class LitmusLLLLOutcome( } final override fun toList() = listOf(r1, r2, r3, r4) + final override fun parseOutcome(str: String): LitmusLLLLOutcome { + val rs = str.split(", ").map(String::toLong) + return LitmusLLLLOutcome(rs[0], rs[1], rs[2], rs[3]) + } } fun LitmusOutcomeSpecScope.accept(r1: Long, r2: Long, r3: Long, r4: Long) = diff --git a/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/Codegen.kt b/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/Codegen.kt index 79ce4fa..6f035ee 100644 --- a/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/Codegen.kt +++ b/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/Codegen.kt @@ -19,7 +19,7 @@ fun generateWrapperFile(test: LitmusTest<*>, generatedSrc: Path): Boolean { val targetCode = try { generateWrapperCode(test) } catch (e: Throwable) { - System.err.println("WARNING: could not generate wrapper for ${test.alias} because: ${e.message}") + System.err.println("WARNING: could not generate wrapper for ${test.alias} because:\n" + e.stackTraceToString()) return false } targetFile.writeText(targetCode) @@ -37,12 +37,15 @@ private fun generateWrapperCode(test: LitmusTest<*>): String { val outcomeTypeName = autoOutcomeClassList.first().simpleName!! .removePrefix("Litmus") .removeSuffix("Outcome") - val (outcomeVarType, outcomeVarCount) = when (outcomeTypeName) { - "I" -> "Integer" to 1 - "II" -> "Integer" to 2 - "III" -> "Integer" to 3 - "IIII" -> "Integer" to 4 - else -> error("unknown AutoOutcome type $outcomeTypeName") + + val outcomeVarTypes = outcomeTypeName.map { c -> + when (c) { + 'I' -> "Integer" + 'L' -> "Long" + 'Z' -> "Boolean" + // TODO: add others once they are created + else -> error("unrecognized outcome type '$c'") + } } val javaTestGetter: String = run { @@ -56,8 +59,8 @@ private fun generateWrapperCode(test: LitmusTest<*>): String { """ @Arbiter public void a($jcstressResultClassName r) { - List<$outcomeVarType> result = (List<$outcomeVarType>) (Object) ((LitmusAutoOutcome) fA.invoke(state)).toList(); - ${List(outcomeVarCount) { "r.r${it + 1} = result.get($it);" }.joinToString("\n ")} + List result = (List) (Object) ((LitmusAutoOutcome) fA.invoke(state)).toList(); + ${List(outcomeVarTypes.size) { "r.r${it + 1} = (${outcomeVarTypes[it]}) result.get($it);" }.joinToString("\n ")} } """.trim() } diff --git a/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/JCStressRunner.kt b/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/JCStressRunner.kt index 2f0f731..83a7f48 100644 --- a/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/JCStressRunner.kt +++ b/jcstress-wrapper/src/main/kotlin/org/jetbrains/litmuskt/JCStressRunner.kt @@ -1,5 +1,6 @@ package org.jetbrains.litmuskt +import org.jetbrains.litmuskt.autooutcomes.LitmusAutoOutcome import org.jetbrains.litmuskt.barriers.JvmCyclicBarrier import java.nio.file.Files import java.nio.file.Path @@ -109,9 +110,6 @@ class JCStressRunner( if (Files.notExists(resultsFile)) return null var lines = Files.lines(resultsFile).asSequence() - val allOutcomes = test.outcomeSpec.all - val outcomeStrings = allOutcomes.associateBy { it.toString().trim('(', ')') } - // get the number of observed outcomes lines = lines.dropWhile { !it.contains("Observed States") } val observedOutcomesLine = lines.splitFirst().let { (first, rest) -> lines = rest; first } @@ -120,9 +118,10 @@ class JCStressRunner( // skip to with outcomes lines = lines.drop(3) val linesOutcomes = lines.splitTake(observedSize).let { (first, rest) -> lines = rest; first } + val outcomeParser = test.stateProducer() as LitmusAutoOutcome val outcomesOrdered = linesOutcomes.map { val outcomeString = parseElementData(it) - outcomeStrings[outcomeString] ?: error("unrecognized outcome: $outcomeString") + outcomeParser.parseOutcome(outcomeString) }.toList() // lines with "bgColor" and "width" are the only ones with data