debug information test: instantiate a single thread for all tests under same test class
This commit is contained in:
committed by
max-kammerer
parent
0a2812f83b
commit
2c78f1fe85
+105
-92
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.debugInformation
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.util.PathUtil
|
||||
import com.intellij.util.SystemProperties
|
||||
import com.sun.jdi.VirtualMachine
|
||||
@@ -25,6 +26,10 @@ 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 org.junit.After
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import java.io.File
|
||||
import java.lang.IllegalStateException
|
||||
import java.net.URLClassLoader
|
||||
@@ -32,88 +37,99 @@ 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"
|
||||
companion object {
|
||||
const val DEBUG_ADDRESS = "127.0.0.1"
|
||||
const val MAIN_CLASS = "org.jetbrains.kotlin.test.clientserver.TestProcessServer"
|
||||
const val TEST_CLASS = "TestKt"
|
||||
const val BOX_METHOD = "box"
|
||||
const val LINENUMBER_PREFIX = "// LINENUMBERS"
|
||||
var proxyPort = 0
|
||||
lateinit var process: Process
|
||||
lateinit var virtualMachine: VirtualMachine
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setUpTest() {
|
||||
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()
|
||||
}
|
||||
|
||||
private 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(
|
||||
PathUtil.getJarPathForClass(TestProcessServer::class.java),
|
||||
PathUtil.getJarPathForClass(Delegates::class.java) // Add Kotlin runtime JAR
|
||||
)
|
||||
|
||||
val javaExecutablePath = findJavaExecutable().absolutePath
|
||||
val command = arrayOf(
|
||||
if (SystemInfo.isWindows) "\"$javaExecutablePath\"" else javaExecutablePath,
|
||||
"-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)
|
||||
})
|
||||
}
|
||||
|
||||
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()) }
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@JvmStatic
|
||||
fun tearDownTest() {
|
||||
process.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
@Before
|
||||
public override fun setUp() {
|
||||
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 {
|
||||
|
||||
}
|
||||
@After
|
||||
public override fun tearDown() {
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
@@ -146,9 +162,9 @@ abstract class AbstractSteppingTest : CodegenTestCase() {
|
||||
classFileFactory.writeAllTo(classesDir)
|
||||
|
||||
try {
|
||||
doTest(lineNumbers, classesDir, virtualMachine!!, classBuilderFactory, classFileFactory, generationState)
|
||||
doTest(lineNumbers, classesDir, virtualMachine, classBuilderFactory, classFileFactory, generationState)
|
||||
} finally {
|
||||
//process.destroy()
|
||||
|
||||
}
|
||||
} finally {
|
||||
tempDirForTest.deleteRecursively()
|
||||
@@ -200,18 +216,20 @@ abstract class AbstractSteppingTest : CodegenTestCase() {
|
||||
is VMDeathEvent, is VMDisconnectEvent -> {
|
||||
break@vmLoop
|
||||
}
|
||||
// We start VM with option suspend=n, in case VMStartEvent is still received, discard.
|
||||
// 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()
|
||||
if (manager.stepRequests().isEmpty()) {
|
||||
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.*")
|
||||
}
|
||||
manager.stepRequests().map { it.enable() }
|
||||
shouldRecordSteps = true
|
||||
loggedEvents.add(event)
|
||||
}
|
||||
@@ -227,6 +245,7 @@ abstract class AbstractSteppingTest : CodegenTestCase() {
|
||||
}
|
||||
is MethodExitEvent -> {
|
||||
if (event.location().method().name() == BOX_METHOD) {
|
||||
manager.stepRequests().map { it.disable() }
|
||||
break@vmLoop
|
||||
}
|
||||
}
|
||||
@@ -244,12 +263,6 @@ abstract class AbstractSteppingTest : CodegenTestCase() {
|
||||
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")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user