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
+20
View File
@@ -0,0 +1,20 @@
//FILE: test.kt
data class someClass(val a: Double, val b: Double)
fun box() {
val a = someClass(1.0, 2.0)
val b = a.copy(b = 3.0)
}
// IGNORE_BACKEND: JVM_IR
// LOCAL VARIABLES
// TestKt:6:
// someClass:3: a:double, b:double
// TestKt:6:
// TestKt:7: a:someClass
// someClass:3: a:double, b:double
// someClass.copy(double, double)+9: a:double, b:double
// someClass.copy$default(someClass, double, double, int, java.lang.Object)+30:
// TestKt:7: a:someClass
// TestKt:8: a:someClass, b:someClass
@@ -0,0 +1,20 @@
//FILE: test.kt
// WITH_RUNTIME
fun box() {
val map: Map<String, String> = mapOf("1" to "23")
for ((a, b)
in map) {
a + b
}
}
// IGNORE_BACKEND: JVM_IR
// LOCAL VARIABLES
// TestKt:6:
// TestKt:8: map:java.util.Collections$SingletonMap
// TestKt:7: map:java.util.Collections$SingletonMap
// TestKt:9: map:java.util.Collections$SingletonMap, a:java.lang.String, b:java.lang.String
// TestKt:7: map:java.util.Collections$SingletonMap
// TestKt:8: map:java.util.Collections$SingletonMap
// TestKt:11: map:java.util.Collections$SingletonMap
@@ -0,0 +1,20 @@
//FILE: test.kt
data class A(val x: String, val y: Int)
fun foo(a: A, block: (A) -> String): String = block(a)
fun box() {
foo(A("O", 123)) { (x, y) -> x + y }
}
// IGNORE_BACKEND: JVM_IR
// LOCAL VARIABLES
// TestKt:8:
// A:3: x:java.lang.String, y:int
// TestKt:8:
// TestKt:5: $dstr$x$y:A
// TestKt$box$1:8:
// TestKt$box$1.invoke(java.lang.Object)+8: a:A, block:TestKt$box$1
// TestKt:5: a:A, block:TestKt$box$1
// TestKt:8:
// TestKt:9:
+16
View File
@@ -0,0 +1,16 @@
//FILE: test.kt
fun foo() {
fun bar() {
}
}
fun box() {
foo()
}
// IGNORE_BACKEND: JVM_IR
// LOCAL VARIABLES
// TestKt:9:
// TestKt:4: $fun$bar$1:TestKt$foo$1
// TestKt:6: $fun$bar$1:TestKt$foo$1
// TestKt:10:
@@ -0,0 +1,49 @@
//FILE: test.kt
data class A(val x: Double = 1.0, val y: String = "", val z: Char = '0')
fun foo(a: A, block: (A, String, Int) -> String): String = block(a, "", 1)
val arrayOfA: Array<A> = Array(1) { A() }
fun box() {
foo(A()) {
(x, _, y), _, w ->
val (a, _, c) = A()
val (_, `_`, d) = A()
for ((_, q) in arrayOfA) {
}
""
}
}
// IGNORE_BACKEND: JVM_IR
// LOCAL VARIABLES
// TestKt:11:
// A:3:
// A:3: x:double, y:java.lang.String, z:char
// A:3:
// TestKt:11:
// TestKt:5: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int
// TestKt$box$1:14:
// A:3: x:double, y:java.lang.String, z:char
// A:3:
// A:3: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int, x:double, y:char
// TestKt$box$1:14: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int, x:double, y:char, a:double, c:char
// TestKt$box$1:15:
// A:3: x:double, y:java.lang.String, z:char
// A:3:
// A:3: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int, x:double, y:char, a:double, c:char
// TestKt$box$1:15: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int, x:double, y:char, a:double, c:char, _:java.lang.String, d:char
// TestKt$box$1:17:
// TestKt:7: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int, x:double, y:char, a:double, c:char, _:java.lang.String, d:char
// TestKt$box$1:17: $dstr$x$_u24__u24$y:A, $noName_1:java.lang.String, w:int, x:double, y:char, a:double, c:char, _:java.lang.String, d:char
// TestKt$box$1:21:
// TestKt$box$1.invoke(java.lang.Object, java.lang.Object, java.lang.Object)+19: a:A, block:TestKt$box$1
// TestKt:5: a:A, block:TestKt$box$1
// TestKt:11:
// TestKt:23:
@@ -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)
}
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.debugInformation;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/debug/localVariables")
@TestDataPath("$PROJECT_ROOT")
@RunWith(BlockJUnit4ClassRunner.class)
public class IrLocalVariableTestGenerated extends AbstractIrLocalVariableTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath);
}
@Test
public void testAllFilesPresentInLocalVariables() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/debug/localVariables"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("copyFunction.kt")
public void testCopyFunction() throws Exception {
runTest("compiler/testData/debug/localVariables/copyFunction.kt");
}
@Test
@TestMetadata("destructuringInFor.kt")
public void testDestructuringInFor() throws Exception {
runTest("compiler/testData/debug/localVariables/destructuringInFor.kt");
}
@Test
@TestMetadata("destructuringInLambdas.kt")
public void testDestructuringInLambdas() throws Exception {
runTest("compiler/testData/debug/localVariables/destructuringInLambdas.kt");
}
@Test
@TestMetadata("localFun.kt")
public void testLocalFun() throws Exception {
runTest("compiler/testData/debug/localVariables/localFun.kt");
}
@Test
@TestMetadata("underscoreNames.kt")
public void testUnderscoreNames() throws Exception {
runTest("compiler/testData/debug/localVariables/underscoreNames.kt");
}
}
@@ -0,0 +1,63 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.debugInformation;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/debug/localVariables")
@TestDataPath("$PROJECT_ROOT")
@RunWith(BlockJUnit4ClassRunner.class)
public class LocalVariableTestGenerated extends AbstractLocalVariableTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@Test
public void testAllFilesPresentInLocalVariables() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/debug/localVariables"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
}
@Test
@TestMetadata("copyFunction.kt")
public void testCopyFunction() throws Exception {
runTest("compiler/testData/debug/localVariables/copyFunction.kt");
}
@Test
@TestMetadata("destructuringInFor.kt")
public void testDestructuringInFor() throws Exception {
runTest("compiler/testData/debug/localVariables/destructuringInFor.kt");
}
@Test
@TestMetadata("destructuringInLambdas.kt")
public void testDestructuringInLambdas() throws Exception {
runTest("compiler/testData/debug/localVariables/destructuringInLambdas.kt");
}
@Test
@TestMetadata("localFun.kt")
public void testLocalFun() throws Exception {
runTest("compiler/testData/debug/localVariables/localFun.kt");
}
@Test
@TestMetadata("underscoreNames.kt")
public void testUnderscoreNames() throws Exception {
runTest("compiler/testData/debug/localVariables/underscoreNames.kt");
}
}
@@ -14,7 +14,9 @@ import org.jetbrains.kotlin.checkers.*
import org.jetbrains.kotlin.checkers.javac.*
import org.jetbrains.kotlin.cli.AbstractCliTest
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.debugInformation.AbstractIrLocalVariableTest
import org.jetbrains.kotlin.codegen.debugInformation.AbstractIrSteppingTest
import org.jetbrains.kotlin.codegen.debugInformation.AbstractLocalVariableTest
import org.jetbrains.kotlin.codegen.debugInformation.AbstractSteppingTest
import org.jetbrains.kotlin.codegen.defaultConstructor.AbstractDefaultArgumentsReflectionTest
import org.jetbrains.kotlin.codegen.flags.AbstractWriteFlagsTest
@@ -373,6 +375,10 @@ fun main(args: Array<String>) {
model("debug/stepping", targetBackend = TargetBackend.JVM)
}
testClass<AbstractLocalVariableTest>(useJunit4 = true) {
model("debug/localVariables", targetBackend = TargetBackend.JVM)
}
testClass<AbstractLocalClassProtoTest> {
model("serialization/local")
}
@@ -466,6 +472,10 @@ fun main(args: Array<String>) {
model("debug/stepping", targetBackend = TargetBackend.JVM_IR)
}
testClass<AbstractIrLocalVariableTest>(useJunit4 = true) {
model("debug/localVariables", targetBackend = TargetBackend.JVM_IR)
}
testClass<AbstractIrBlackBoxInlineCodegenTest> {
model("codegen/boxInline", targetBackend = TargetBackend.JVM_IR)
}