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:
committed by
Ilmir Usmanov
parent
6b73ef4b0b
commit
6454cfad87
@@ -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:
|
||||
@@ -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:
|
||||
+8
-4
@@ -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")
|
||||
|
||||
+12
@@ -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)
|
||||
}
|
||||
}
|
||||
+74
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+63
@@ -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");
|
||||
}
|
||||
}
|
||||
Generated
+63
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user