add local variable test. This test runs box() method and checks local variable types and names avaiable at every step.

This commit is contained in:
Jiaxiang Chen
2019-10-21 17:29:04 -07:00
committed by Ilmir Usmanov
parent 6b73ef4b0b
commit 6454cfad87
11 changed files with 355 additions and 4 deletions
@@ -11,7 +11,7 @@ import com.intellij.util.SystemProperties
import com.sun.jdi.VirtualMachine
import com.sun.jdi.event.*
import com.sun.jdi.request.EventRequest
import com.sun.jdi.request.EventRequest.SUSPEND_NONE
import com.sun.jdi.request.EventRequest.SUSPEND_ALL
import com.sun.jdi.request.StepRequest
import com.sun.tools.jdi.SocketAttachingConnector
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
@@ -53,7 +53,7 @@ abstract class AbstractDebugTest : CodegenTestCase() {
val methodExitReq = manager.createMethodExitRequest()
methodExitReq.addClassFilter(TEST_CLASS)
methodExitReq.setSuspendPolicy(EventRequest.SUSPEND_NONE)
methodExitReq.setSuspendPolicy(EventRequest.SUSPEND_ALL)
methodExitReq.enable()
}
@@ -178,7 +178,7 @@ abstract class AbstractDebugTest : CodegenTestCase() {
var inBoxMethod = false
vmLoop@
while (true) {
val eventSet = virtualMachine.eventQueue().remove()
val eventSet = virtualMachine.eventQueue().remove(100)
for (event in eventSet) {
when (event) {
is VMDeathEvent, is VMDisconnectEvent -> {
@@ -192,7 +192,7 @@ abstract class AbstractDebugTest : CodegenTestCase() {
if (!inBoxMethod && event.location().method().name() == BOX_METHOD) {
if (manager.stepRequests().isEmpty()) {
val stepReq = manager.createStepRequest(event.thread(), StepRequest.STEP_LINE, StepRequest.STEP_INTO)
stepReq.setSuspendPolicy(SUSPEND_NONE)
stepReq.setSuspendPolicy(SUSPEND_ALL)
stepReq.addClassExclusionFilter("java.*")
stepReq.addClassExclusionFilter("sun.*")
stepReq.addClassExclusionFilter("kotlin.*")
@@ -206,17 +206,21 @@ abstract class AbstractDebugTest : CodegenTestCase() {
is StepEvent -> {
// Handle the case where an Exception causing program to exit without MethodExitEvent.
if (inBoxMethod && event.location().method().name() == "run") {
virtualMachine.resume()
break@vmLoop
}
if (inBoxMethod) {
storeStep(loggedItems, event)
}
virtualMachine.resume()
}
is MethodExitEvent -> {
if (event.location().method().name() == BOX_METHOD) {
manager.stepRequests().map { it.disable() }
virtualMachine.resume()
break@vmLoop
}
virtualMachine.resume()
}
else -> {
throw IllegalStateException("event not handled: $event")
@@ -0,0 +1,12 @@
package org.jetbrains.kotlin.codegen.debugInformation
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
abstract class AbstractIrLocalVariableTest : AbstractLocalVariableTest() {
override fun updateConfiguration(configuration: CompilerConfiguration) {
super.updateConfiguration(configuration)
configuration.put(JVMConfigurationKeys.IR, true)
}
}
@@ -0,0 +1,74 @@
package org.jetbrains.kotlin.codegen.debugInformation
import com.sun.jdi.LocalVariable
import com.sun.jdi.StackFrame
import com.sun.jdi.VirtualMachine
import com.sun.jdi.event.Event
import com.sun.jdi.event.LocatableEvent
import junit.framework.TestCase
import org.junit.AfterClass
import org.junit.BeforeClass
import java.io.File
abstract class AbstractLocalVariableTest : AbstractDebugTest() {
override val virtualMachine: VirtualMachine = Companion.virtualMachine
override val proxyPort: Int = Companion.proxyPort
companion object {
const val LOCAL_VARIABLES = "// LOCAL VARIABLES"
var proxyPort = 0
lateinit var process: Process
lateinit var virtualMachine: VirtualMachine
@BeforeClass
@JvmStatic
fun setUpTest() {
val (process, port) = startDebuggeeProcess()
this.process = process
virtualMachine = attachDebugger(port)
setUpVM(virtualMachine)
proxyPort = getProxyPort(process)
}
@AfterClass
@JvmStatic
fun tearDownTest() {
process.destroy()
}
}
override fun storeStep(loggedItems: ArrayList<Any>, event: Event) {
waitUntil { (event as LocatableEvent).thread().isSuspended }
val visibleVars = (event as LocatableEvent)
.thread()
.frame(0)
.visibleVariables()
.map { variable -> toRecord(event.thread().frame(0), variable) }
.joinToString(", ")
loggedItems.add("${event.location()}: $visibleVars".trim())
}
override fun checkResult(wholeFile: File, loggedItems: List<Any>) {
val expectedLocalVariables = wholeFile
.readLines()
.dropWhile { !it.startsWith(LOCAL_VARIABLES) }
.drop(1)
.map { it.drop(3) }
.joinToString("\n")
val actualLocalVariables = loggedItems.joinToString("\n")
TestCase.assertEquals(expectedLocalVariables, actualLocalVariables)
}
private fun toRecord(frame: StackFrame, variable: LocalVariable): String {
return "${variable.name()}:${frame.getValue(variable)?.type()?.name() ?: "null"}"
}
private fun waitUntil(condition: () -> Boolean) {
while (!condition()) {
Thread.sleep(10)
}
}
}