[test] Factor out helper classes of LocalVariableDebugRunner

We want to use them in non JVM-specific tests.
This commit is contained in:
Sergej Jaskiewicz
2022-10-17 15:25:38 +02:00
committed by Space Team
parent 873b84491d
commit 7692423e44
2 changed files with 62 additions and 42 deletions
@@ -16,9 +16,7 @@ import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.sourceProviders.MainFunctionForBlackBoxTestsSourceProvider.Companion.BOX_MAIN_FILE_NAME
import org.jetbrains.kotlin.test.utils.SteppingTestLoggedData
import org.jetbrains.kotlin.test.utils.checkSteppingTestResult
import org.jetbrains.kotlin.test.utils.formatAsSteppingTestExpectation
import org.jetbrains.kotlin.test.utils.*
import java.io.File
import java.net.URL
@@ -161,8 +159,8 @@ abstract class DebugRunner(testServices: TestServices) : JvmBoxRunner(testServic
virtualMachine.resume()
}
fun Location.formatAsExpectation() =
formatAsSteppingTestExpectation(sourceName(), lineNumber(), method().name(), method().isSynthetic)
fun Location.formatAsExpectation(visibleVars: List<LocalVariableRecord>? = null) =
formatAsSteppingTestExpectation(sourceName(), lineNumber(), method().name(), method().isSynthetic, visibleVars)
fun setupMethodEntryAndExitRequests(virtualMachine: VirtualMachine) {
val manager = virtualMachine.eventRequestManager()
@@ -204,40 +202,11 @@ class SteppingDebugRunner(testServices: TestServices) : DebugRunner(testServices
}
class LocalVariableDebugRunner(testServices: TestServices) : DebugRunner(testServices) {
interface LocalValue
class LocalPrimitive(val value: String, val valueType: String) : LocalValue {
override fun toString(): String {
return "$value:$valueType"
}
}
class LocalReference(val id: String, val referenceType: String) : LocalValue {
override fun toString(): String {
return referenceType
}
}
class LocalNullValue : LocalValue {
override fun toString(): String {
return "null"
}
}
class LocalVariableRecord(
val variable: String,
val variableType: String,
val value: LocalValue
) {
override fun toString(): String {
return "$variable:$variableType=$value"
}
}
private fun toRecord(frame: StackFrame, variable: LocalVariable): LocalVariableRecord {
val value = frame.getValue(variable)
val valueRecord = if (value == null) {
LocalNullValue()
LocalNullValue
} else if (value is ObjectReference && value.referenceType().name() != "java.lang.String") {
LocalReference(value.uniqueID().toString(), value.referenceType().name())
} else {
@@ -269,7 +238,7 @@ class LocalVariableDebugRunner(testServices: TestServices) : DebugRunner(testSer
SteppingTestLoggedData(
location.lineNumber(),
false,
"${location.formatAsExpectation()}: ${visibleVars.joinToString(", ")}".trim()
location.formatAsExpectation(visibleVars)
)
)
}
@@ -14,6 +14,42 @@ import java.io.File
data class SteppingTestLoggedData(val line: Int, val isSynthetic: Boolean, val expectation: String)
sealed interface LocalValue
class LocalPrimitive(val value: String, val valueType: String) : LocalValue {
override fun toString(): String {
return "$value:$valueType"
}
}
class LocalReference(val id: String, val referenceType: String) : LocalValue {
override fun toString(): String {
return referenceType
}
}
object LocalNullValue : LocalValue {
override fun toString(): String {
return "null"
}
}
class LocalVariableRecord(
val variable: String,
val variableType: String?,
val value: LocalValue
) {
override fun toString(): String = buildString {
append(variable)
if (variableType != null) {
append(":")
append(variableType)
}
append("=")
append(value)
}
}
private const val EXPECTATIONS_MARKER = "// EXPECTATIONS"
private const val FORCE_STEP_INTO_MARKER = "// FORCE_STEP_INTO"
@@ -27,7 +63,7 @@ fun checkSteppingTestResult(
val lines = wholeFile.readLines()
val forceStepInto = lines.any { it.startsWith(FORCE_STEP_INTO_MARKER) }
val actualLineNumbers = compressSequencesWithoutLinenumber(loggedItems)
val actualLineNumbers = compressSequencesWithoutLineNumber(loggedItems)
.filter {
// Ignore synthetic code with no line number information unless force step into behavior is requested.
forceStepInto || !it.isSynthetic
@@ -88,7 +124,7 @@ fun checkSteppingTestResult(
* print as byte offsets. This avoids overspecifying code generation
* strategy in debug tests.
*/
private fun compressSequencesWithoutLinenumber(loggedItems: List<SteppingTestLoggedData>): List<SteppingTestLoggedData> {
private fun compressSequencesWithoutLineNumber(loggedItems: List<SteppingTestLoggedData>): List<SteppingTestLoggedData> {
if (loggedItems.isEmpty()) return listOf()
val logIterator = loggedItems.iterator()
@@ -105,7 +141,22 @@ private fun compressSequencesWithoutLinenumber(loggedItems: List<SteppingTestLog
return result
}
fun formatAsSteppingTestExpectation(sourceName: String, lineNumber: Int, functionName: String, isSynthetic: Boolean): String {
val synthetic = if (isSynthetic) " (synthetic)" else ""
return "$sourceName:$lineNumber $functionName$synthetic"
}
fun formatAsSteppingTestExpectation(
sourceName: String,
lineNumber: Int,
functionName: String,
isSynthetic: Boolean,
visibleVars: List<LocalVariableRecord>? = null
) = buildString {
append(sourceName)
append(':')
append(lineNumber)
append(' ')
append(functionName)
if (isSynthetic)
append(" (synthetic)")
if (visibleVars != null) {
append(": ")
visibleVars.joinTo(this)
}
}.trim()