diff --git a/compiler/testData/debug/stepping/IfTrueThenFalse.kt b/compiler/testData/debug/stepping/IfTrueThenFalse.kt new file mode 100644 index 00000000000..58e8d42853d --- /dev/null +++ b/compiler/testData/debug/stepping/IfTrueThenFalse.kt @@ -0,0 +1,16 @@ +//FILE: test.kt +fun cond() = false + +fun box() { + if (cond()) + cond() + else + false +} + +// LINENUMBERS +// TestKt.box():5 +// TestKt.cond():2 +// TestKt.box():5 +// TestKt.box():8 +// TestKt.box():9 diff --git a/compiler/testData/debug/stepping/conjunction.kt b/compiler/testData/debug/stepping/conjunction.kt new file mode 100644 index 00000000000..29ea7974433 --- /dev/null +++ b/compiler/testData/debug/stepping/conjunction.kt @@ -0,0 +1,36 @@ +//FILE: test.kt +fun box() { + val k = if (getA() + && getB() + && getC() + && getD()) { + true + } else { + false + } +} + +fun getA() = true + +fun getB() = true + +fun getC() = false + +fun getD() = true + +// IGNORE_BACKEND: JVM_IR +// IR backend is missing a line number 3 in box() after stepping on line 9 for getting the result of false + +// LINENUMBERS +// TestKt.box():3 +// TestKt.getA():13 +// TestKt.box():3 +// TestKt.box():4 +// TestKt.getB():15 +// TestKt.box():4 +// TestKt.box():5 +// TestKt.getC():17 +// TestKt.box():5 +// TestKt.box():9 +// TestKt.box():3 +// TestKt.box():11 diff --git a/compiler/testData/debug/stepping/functionInAnotherFile.kt b/compiler/testData/debug/stepping/functionInAnotherFile.kt new file mode 100644 index 00000000000..cf1a0fcc520 --- /dev/null +++ b/compiler/testData/debug/stepping/functionInAnotherFile.kt @@ -0,0 +1,38 @@ +//FILE: foo.kt +import bar +fun foo(x: Int): Int { + if (x >= 0) { // 4 + return x // 5 + } + return bar(x) // 7 +} + +//FILE: test.kt +import foo +fun box() { + foo(-3) //4 +} + +fun bar(x: Int) = + if (x < 0) { //8 + foo(0) + } else { // 10 + foo(x) + } + +// IGNORE_BACKEND: JVM_IR + +// IR backend has bar().12 replaced as bar().8 for returning bar() function result. +// LINENUMBERS +// TestKt.box():4 +// FooKt.foo(int):4 +// FooKt.foo(int):7 +// TestKt.bar(int):8 +// TestKt.bar(int):9 +// FooKt.foo(int):4 +// FooKt.foo(int):5 +// TestKt.bar(int):9 +// TestKt.bar(int):12 +// FooKt.foo(int):7 +// TestKt.box():4 +// TestKt.box():5 diff --git a/compiler/testData/debug/stepping/if.kt b/compiler/testData/debug/stepping/if.kt new file mode 100644 index 00000000000..1fdeb9c2de2 --- /dev/null +++ b/compiler/testData/debug/stepping/if.kt @@ -0,0 +1,26 @@ +//FILE: test.kt +fun box(): Int { + if ( + getB() == + getA()) + return 0 + return getB() +} + +fun getA() = 3 + +inline fun getB(): Int { + return 1 +} + +// IGNORE_BACKEND: JVM_IR +// old backend is missing a line number after return from inline function call, actually IR backend results seems more right. + +// LINENUMBERS +// TestKt.box():4 +// TestKt.box():13 +// TestKt.box():5 +// TestKt.getA():10 +// TestKt.box():5 +// TestKt.box():7 +// TestKt.box():13 diff --git a/compiler/testData/debug/stepping/recursion.kt b/compiler/testData/debug/stepping/recursion.kt new file mode 100644 index 00000000000..c26f2275684 --- /dev/null +++ b/compiler/testData/debug/stepping/recursion.kt @@ -0,0 +1,26 @@ +//FILE: test.kt +fun box() { + val n = 3 + val k = foo(n) +} + +fun foo(n :Int ) : Int { + if (n == 1 || n == 0) { + return 1 + } + return foo(n-1) * n +} + +// LINENUMBERS +// TestKt.box():3 +// TestKt.box():4 +// TestKt.foo(int):8 +// TestKt.foo(int):11 +// TestKt.foo(int):8 +// TestKt.foo(int):11 +// TestKt.foo(int):8 +// TestKt.foo(int):9 +// TestKt.foo(int):11 +// TestKt.foo(int):11 +// TestKt.box():4 +// TestKt.box():5 diff --git a/compiler/testData/debug/stepping/throwException.kt b/compiler/testData/debug/stepping/throwException.kt new file mode 100644 index 00000000000..c53a580df36 --- /dev/null +++ b/compiler/testData/debug/stepping/throwException.kt @@ -0,0 +1,29 @@ +//FILE: test.kt +fun box() { + val a = 1 + val b = 2 + try { + throwIfLess(a, b) + } catch (e: java.lang.Exception) { + throwIfLess(a, b) + } + throwIfLess(b,a) +} + +fun throwIfLess(a: Int, b: Int) { + if (a): Method? { //Use only JDK 1.6 compatible api object TestProcessServer { + const val DEBUG_TEST = "--debugTest" + private val executor = Executors.newFixedThreadPool(1)!! @Volatile @@ -63,13 +65,21 @@ object TestProcessServer { private lateinit var serverSocket: ServerSocket + private var suppressOutput = false + private var allocatePort = false + @JvmStatic fun main(args: Array) { - val portNumber = args[0].toInt() - println("Starting server on port $portNumber...") + if (args[0] == DEBUG_TEST) { + suppressOutput = true + allocatePort = true + } + val portNumber = if (allocatePort) 0 else args[0].toInt() + println("Starting server on port $portNumber...") val serverSocket = ServerSocket(portNumber) - sheduleShutdownProcess() + println("...server started on port ${serverSocket.localPort}") + scheduleShutdownProcess() try { while (true) { @@ -78,7 +88,7 @@ object TestProcessServer { val clientSocket = serverSocket.accept() isProcessingTask = true println("Socket established...") - executor.execute(ServerTest(clientSocket)) + executor.execute(ServerTest(clientSocket, suppressOutput)) } } finally { @@ -89,7 +99,7 @@ object TestProcessServer { } } - private fun sheduleShutdownProcess() { + private fun scheduleShutdownProcess() { handler = scheduler.scheduleAtFixedRate({ if (!isProcessingTask && (System.currentTimeMillis() - lastTime) >= 60 * 1000 /*60 sec*/) { println("Stopping server...") @@ -97,15 +107,21 @@ object TestProcessServer { } }, 60, 60, TimeUnit.SECONDS) } + + private fun printlnTest(text: String) { + if (!suppressOutput) { + println(text) + } + } } -private class ServerTest(val clientSocket: Socket) : Runnable { +private class ServerTest(val clientSocket: Socket, val suppressOutput: Boolean) : Runnable { private lateinit var className: String private lateinit var testMethod: String override fun run() { val input = ObjectInputStream(clientSocket.getInputStream()) - val output = ObjectOutputStream(clientSocket.getOutputStream()) + val output = if (suppressOutput) null else ObjectOutputStream(clientSocket.getOutputStream()) try { var message = input.readObject() as MessageHeader assert(message == MessageHeader.NEW_TEST, { "New test marker missed, but $message received" }) @@ -119,13 +135,13 @@ private class ServerTest(val clientSocket: Socket) : Runnable { val classPath = input.readObject() as Array val result = executeTest(URLClassLoader(classPath, JDK_EXT_JARS_CLASS_LOADER)) - output.writeObject(MessageHeader.RESULT) - output.writeObject(result) + output?.writeObject(MessageHeader.RESULT) + output?.writeObject(result) } catch (e: Throwable) { - output.writeObject(MessageHeader.ERROR) - output.writeObject(e) + output?.writeObject(MessageHeader.ERROR) + output?.writeObject(e) } finally { - output.close() + output?.close() input.close() clientSocket.close() } diff --git a/compiler/tests-common-jvm6/tests/org/jetbrains/kotlin/test/clientserver/TestProxy.kt b/compiler/tests-common-jvm6/tests/org/jetbrains/kotlin/test/clientserver/TestProxy.kt index b052d6498d6..0b9ebc86bca 100644 --- a/compiler/tests-common-jvm6/tests/org/jetbrains/kotlin/test/clientserver/TestProxy.kt +++ b/compiler/tests-common-jvm6/tests/org/jetbrains/kotlin/test/clientserver/TestProxy.kt @@ -54,6 +54,25 @@ class TestProxy(val serverPort: Int, val testClass: String, val classPath: List< } } + fun runTestNoOutput(): String { + return Socket("localhost", serverPort).use { clientSocket -> + + val output = ObjectOutputStream(clientSocket.getOutputStream()) + try { + output.writeObject(MessageHeader.NEW_TEST) + output.writeObject(testClass) + output.writeObject("box") + + output.writeObject(MessageHeader.CLASS_PATH) + //filter out jdk libs + output.writeObject(filterOutJdkJars(classPath).toTypedArray()) + return "OK" + } finally { + output.close() + } + } + } + fun filterOutJdkJars(classPath: List): List { val javaHome = System.getProperty("java.home") val javaFolder = File(javaHome) diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/debugInformation/AbstractIrSteppingTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/debugInformation/AbstractIrSteppingTest.kt new file mode 100644 index 00000000000..5f58ba70452 --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/debugInformation/AbstractIrSteppingTest.kt @@ -0,0 +1,17 @@ +/* + * 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 org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.config.JVMConfigurationKeys + +abstract class AbstractIrSteppingTest : AbstractSteppingTest() { + + override fun updateConfiguration(configuration: CompilerConfiguration) { + super.updateConfiguration(configuration) + configuration.put(JVMConfigurationKeys.IR, true) + } +} \ No newline at end of file diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/debugInformation/AbstractSteppingTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/debugInformation/AbstractSteppingTest.kt new file mode 100644 index 00000000000..ef7d785e817 --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codegen/debugInformation/AbstractSteppingTest.kt @@ -0,0 +1,259 @@ +/* + * 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.util.PathUtil +import com.intellij.util.SystemProperties +import com.sun.jdi.VirtualMachine +import com.sun.jdi.event.* +import com.sun.jdi.request.EventRequest.SUSPEND_ALL +import com.sun.jdi.request.EventRequest.SUSPEND_NONE +import com.sun.jdi.request.StepRequest +import com.sun.tools.jdi.SocketAttachingConnector +import junit.framework.TestCase +import org.jetbrains.kotlin.backend.common.output.OutputFile +import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection +import org.jetbrains.kotlin.cli.common.output.writeAllTo +import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime +import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.test.ConfigurationKind +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.clientserver.getGeneratedClass +import org.jetbrains.kotlin.test.clientserver.TestProcessServer +import org.jetbrains.kotlin.test.clientserver.TestProxy +import java.io.File +import java.lang.IllegalStateException +import java.net.URLClassLoader +import kotlin.properties.Delegates + +abstract class AbstractSteppingTest : CodegenTestCase() { + + private companion object { + private const val DEBUG_ADDRESS = "127.0.0.1" + private const val MAIN_CLASS = "org.jetbrains.kotlin.test.clientserver.TestProcessServer" + private const val TEST_CLASS = "TestKt" + private const val BOX_METHOD = "box" + private const val LINENUMBER_PREFIX = "// LINENUMBERS" + } + + private var proxyPort = 0 + + private var process: Process? = null + + private var virtualMachine: VirtualMachine? = null + + override fun setUp() { + val debugPort = startDebuggeeProcess() + virtualMachine = attachDebugger(debugPort) + setUpVM(virtualMachine!!) + + val reader = process!!.inputStream.bufferedReader() + reader.readLine() + proxyPort = reader.readLine() + .split("port ") + .last() + .trim() + .toInt() + reader.close() + + super.setUp() + } + + open fun setUpVM(virtualMachine: VirtualMachine) { + val manager = virtualMachine.eventRequestManager() + + val methodEntryReq = manager.createMethodEntryRequest() + methodEntryReq.addClassFilter(TEST_CLASS) + methodEntryReq.setSuspendPolicy(SUSPEND_ALL) + methodEntryReq.enable() + + val methodExitReq = manager.createMethodExitRequest() + methodExitReq.addClassFilter(TEST_CLASS) + methodExitReq.setSuspendPolicy(SUSPEND_NONE) + methodExitReq.enable() + } + + private fun startDebuggeeProcess(): Int{ + val classpath = listOf( + System.getProperty("java.class.path"), + PathUtil.getJarPathForClass(Delegates::class.java) // Add Kotlin runtime JAR + ) + + val command = arrayOf( + findJavaExecutable().absolutePath, + "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=127.0.0.1:0", + "-ea", + "-classpath", classpath.joinToString(File.pathSeparator), + MAIN_CLASS, + TestProcessServer.DEBUG_TEST + ) + + process = ProcessBuilder(*command).start() + return process!!.inputStream.bufferedReader().readLine() + .split("address:") + .last() + .trim() + .toInt() + } + + private fun attachDebugger(port: Int): VirtualMachine { + val connector = SocketAttachingConnector() + return connector.attach(connector.defaultArguments().toMutableMap().apply { + getValue("port").setValue("$port") + getValue("hostname").setValue(DEBUG_ADDRESS) + }) + } + + override fun tearDown() { + try { + process!!.destroy() + } finally { + + } + super.tearDown() + } + + override fun doMultiFileTest(wholeFile: File, files: List) { + createEnvironmentWithMockJdkAndIdeaAnnotations( + ConfigurationKind.ALL, *listOfNotNull( + writeJavaFiles( + files + ) + ).toTypedArray() + ) + + val lineNumbers = wholeFile + .readLines() + .dropWhile { !it.startsWith(LINENUMBER_PREFIX) } + .drop(1) + .map { it.drop(3).trim() } + .joinToString(" ") + + loadMultiFiles(files) + val classBuilderFactory = + OriginCollectingClassBuilderFactory(ClassBuilderMode.FULL) + val generationState = + GenerationUtils.compileFiles(myFiles.psiFiles, myEnvironment, classBuilderFactory) + classFileFactory = generationState.factory + + val tempDirForTest = KotlinTestUtils.tmpDir("debuggerTest") + val classesDir = File(tempDirForTest, "classes") + try { + classFileFactory.writeAllTo(classesDir) + + try { + doTest(lineNumbers, classesDir, virtualMachine!!, classBuilderFactory, classFileFactory, generationState) + } finally { + //process.destroy() + } + } finally { + tempDirForTest.deleteRecursively() + } + } + + private fun invokeBoxInSeparateProcess(classLoader: URLClassLoader, aClass: Class<*>, port: Int): String { + + val classPath = classLoader.extractUrls().toMutableList() + if (classLoader is GeneratedClassLoader) { + val outDir = KotlinTestUtils.tmpDirForTest(this) + val currentOutput = SimpleOutputFileCollection(classLoader.allGeneratedFiles) + currentOutput.writeAllTo(outDir) + classPath.add(0, outDir.toURI().toURL()) + } + + return TestProxy(Integer.valueOf(port), aClass.canonicalName, classPath).runTestNoOutput() + } + + private fun createGeneratedClassLoader(classesDir: File): URLClassLoader { + return URLClassLoader( + listOf(classesDir.toURI().toURL()).toTypedArray(), + ForTestCompileRuntime.runtimeJarClassLoader() + ) + } + + protected open fun doTest( + expectedLineNumbers: String, + classesDir: File, + virtualMachine: VirtualMachine, + factory: OriginCollectingClassBuilderFactory, + classFileFactory: ClassFileFactory, + state: GenerationState + ) { + + val classLoader = createGeneratedClassLoader(classesDir) + val aClass = getGeneratedClass(classLoader, TEST_CLASS) + + val manager = virtualMachine.eventRequestManager() + + invokeBoxInSeparateProcess(classLoader, aClass, proxyPort) + val loggedEvents = ArrayList() + var shouldRecordSteps = false + vmLoop@ + while (true) { + val eventSet = virtualMachine.eventQueue().remove() + for (event in eventSet) { + when (event) { + is VMDeathEvent, is VMDisconnectEvent -> { + break@vmLoop + } + // We start VM with option suspend=n, in case VMStartEvent is still received, discard. + is VMStartEvent -> { + + } + is MethodEntryEvent -> { + if (!shouldRecordSteps && event.location().method().name() == BOX_METHOD) { + val stepReq = manager.createStepRequest(event.thread(), StepRequest.STEP_LINE, StepRequest.STEP_INTO) + stepReq.setSuspendPolicy(SUSPEND_NONE) + stepReq.addClassExclusionFilter("java.*") + stepReq.addClassExclusionFilter("sun.*") + stepReq.addClassExclusionFilter("kotlin.*") + stepReq.enable() + shouldRecordSteps = true + loggedEvents.add(event) + } + virtualMachine.resume() + } + is StepEvent -> { + if (shouldRecordSteps && event.location().method().name() == "run") { + break@vmLoop + } + if (shouldRecordSteps) { + loggedEvents.add(event) + } + } + is MethodExitEvent -> { + if (event.location().method().name() == BOX_METHOD) { + break@vmLoop + } + } + else -> { + throw IllegalStateException("event not handled: $event") + } + } + } + } + + val actualLineNumbers = loggedEvents + .map { event -> + "${(event as LocatableEvent).location().method()}:${event.location().lineNumber()}" + } + TestCase.assertEquals(expectedLineNumbers, actualLineNumbers.joinToString(" ")) + } + + private fun findJavaExecutable(): File { + val javaBin = File(SystemProperties.getJavaHome(), "bin") + return File(javaBin, "java.exe").takeIf { it.exists() } + ?: File(javaBin, "java").also { assert(it.exists()) } + } + + internal val OutputFile.internalName + get() = relativePath.substringBeforeLast(".class") + + internal val OutputFile.qualifiedName + get() = internalName.replace('/', '.') +} + diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/debugInformation/IrSteppingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/debugInformation/IrSteppingTestGenerated.java new file mode 100644 index 00000000000..d41f790a6c3 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/codegen/debugInformation/IrSteppingTestGenerated.java @@ -0,0 +1,61 @@ +/* + * 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.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +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/stepping") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class IrSteppingTestGenerated extends AbstractIrSteppingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM_IR, testDataFilePath); + } + + public void testAllFilesPresentInStepping() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/debug/stepping"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM_IR, true); + } + + @TestMetadata("conjunction.kt") + public void testConjunction() throws Exception { + runTest("compiler/testData/debug/stepping/conjunction.kt"); + } + + @TestMetadata("functionInAnotherFile.kt") + public void testFunctionInAnotherFile() throws Exception { + runTest("compiler/testData/debug/stepping/functionInAnotherFile.kt"); + } + + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/debug/stepping/if.kt"); + } + + @TestMetadata("IfTrueThenFalse.kt") + public void testIfTrueThenFalse() throws Exception { + runTest("compiler/testData/debug/stepping/IfTrueThenFalse.kt"); + } + + @TestMetadata("recursion.kt") + public void testRecursion() throws Exception { + runTest("compiler/testData/debug/stepping/recursion.kt"); + } + + @TestMetadata("throwException.kt") + public void testThrowException() throws Exception { + runTest("compiler/testData/debug/stepping/throwException.kt"); + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/debugInformation/SteppingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/debugInformation/SteppingTestGenerated.java new file mode 100644 index 00000000000..aa5d81a57d6 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/codegen/debugInformation/SteppingTestGenerated.java @@ -0,0 +1,61 @@ +/* + * 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.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +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/stepping") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class SteppingTestGenerated extends AbstractSteppingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); + } + + public void testAllFilesPresentInStepping() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/debug/stepping"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true); + } + + @TestMetadata("conjunction.kt") + public void testConjunction() throws Exception { + runTest("compiler/testData/debug/stepping/conjunction.kt"); + } + + @TestMetadata("functionInAnotherFile.kt") + public void testFunctionInAnotherFile() throws Exception { + runTest("compiler/testData/debug/stepping/functionInAnotherFile.kt"); + } + + @TestMetadata("if.kt") + public void testIf() throws Exception { + runTest("compiler/testData/debug/stepping/if.kt"); + } + + @TestMetadata("IfTrueThenFalse.kt") + public void testIfTrueThenFalse() throws Exception { + runTest("compiler/testData/debug/stepping/IfTrueThenFalse.kt"); + } + + @TestMetadata("recursion.kt") + public void testRecursion() throws Exception { + runTest("compiler/testData/debug/stepping/recursion.kt"); + } + + @TestMetadata("throwException.kt") + public void testThrowException() throws Exception { + runTest("compiler/testData/debug/stepping/throwException.kt"); + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt index 65ac0eece67..653e854ad5a 100644 --- a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt +++ b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt @@ -14,6 +14,8 @@ 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.AbstractIrSteppingTest +import org.jetbrains.kotlin.codegen.debugInformation.AbstractSteppingTest import org.jetbrains.kotlin.codegen.defaultConstructor.AbstractDefaultArgumentsReflectionTest import org.jetbrains.kotlin.codegen.flags.AbstractWriteFlagsTest import org.jetbrains.kotlin.codegen.ir.* @@ -342,6 +344,10 @@ fun main(args: Array) { model("lineNumber") } + testClass { + model("debug/stepping", targetBackend = TargetBackend.JVM) + } + testClass { model("serialization/local") } @@ -419,6 +425,10 @@ fun main(args: Array) { model("lineNumber", targetBackend = TargetBackend.JVM_IR) } + testClass { + model("debug/stepping", targetBackend = TargetBackend.JVM_IR) + } + testClass { model("codegen/boxInline", targetBackend = TargetBackend.JVM_IR) }