Extract jvm6-specific test utils, add codegen on specific jdk tests

This commit is contained in:
Ilya Chernikov
2017-09-18 17:59:04 +02:00
parent 82690fe6b3
commit 51efd717f6
14 changed files with 125 additions and 24 deletions
@@ -34,6 +34,8 @@ import java.util.List;
import static org.jetbrains.kotlin.codegen.TestUtilsKt.*;
import static org.jetbrains.kotlin.test.KotlinTestUtils.assertEqualsToFile;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getBoxMethodOrNull;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass;
public abstract class AbstractBlackBoxCodegenTest extends CodegenTestCase {
@@ -80,6 +80,8 @@ import static org.jetbrains.kotlin.cli.common.output.outputUtils.OutputUtilsKt.w
import static org.jetbrains.kotlin.codegen.CodegenTestUtil.*;
import static org.jetbrains.kotlin.codegen.TestUtilsKt.*;
import static org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getBoxMethodOrNull;
import static org.jetbrains.kotlin.test.clientserver.TestProcessServerKt.getGeneratedClass;
public abstract class CodegenTestCase extends KtUsefulTestCase {
private static final String DEFAULT_TEST_FILE_NAME = "a_test";
@@ -35,23 +35,6 @@ fun clearReflectionCache(classLoader: ClassLoader) {
}
fun getGeneratedClass(classLoader: ClassLoader, className: String): Class<*> {
try {
return classLoader.loadClass(className)
}
catch (e: ClassNotFoundException) {
error("No class file was generated for: " + className)
}
}
fun getBoxMethodOrNull(aClass: Class<*>): Method? {
try {
return aClass.getMethod("box")
}
catch (e: NoSuchMethodException) {
return null
}
}
fun ClassLoader?.extractUrls(): List<URL> {
return (this as? URLClassLoader)?.let {
@@ -1,24 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.test.clientserver
enum class MessageHeader {
NEW_TEST,
CLASS_PATH,
RESULT,
ERROR
}
@@ -1,104 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.test.clientserver
import org.jetbrains.kotlin.codegen.getBoxMethodOrNull
import org.jetbrains.kotlin.codegen.getGeneratedClass
import java.io.File
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.net.ServerSocket
import java.net.Socket
import java.net.URL
import java.net.URLClassLoader
import java.util.concurrent.Executors
//Use only JDK 1.6 compatible api
object TestProcessServer {
val executor = Executors.newFixedThreadPool(1)!!
@JvmStatic
fun main(args: Array<String>) {
val portNumber = args[0].toInt()
println("Starting server on port $portNumber...")
val serverSocket = ServerSocket(portNumber)
try {
while (true) {
val clientSocket = serverSocket.accept()
println("Socket established...")
executor.execute(ServerTest(clientSocket))
}
}
finally {
serverSocket.close()
}
}
}
private class ServerTest(val clientSocket: Socket) : Runnable {
private lateinit var className: String
private lateinit var testMethod: String
override fun run() {
val input = ObjectInputStream(clientSocket.getInputStream())
val output = ObjectOutputStream(clientSocket.getOutputStream())
try {
var message = input.readObject() as MessageHeader
assert(message == MessageHeader.NEW_TEST, { "New test marker missed, but $message received" })
className = input.readObject() as String
testMethod = input.readObject() as String
println("Preparing to execute test $className")
message = input.readObject() as MessageHeader
assert(message == MessageHeader.CLASS_PATH, { "Class path marker missed, but $message received" })
val classPath = input.readObject() as Array<URL>
val result = executeTest(URLClassLoader(classPath, JDK_EXT_JARS_CLASS_LOADER))
output.writeObject(MessageHeader.RESULT)
output.writeObject(result)
}
catch (e: Exception) {
output.writeObject(MessageHeader.ERROR)
output.writeObject(e)
}
finally {
output.close()
input.close()
clientSocket.close()
}
}
fun executeTest(classLoader: ClassLoader): String {
val clazz = getGeneratedClass(classLoader, className)
return getBoxMethodOrNull(clazz)!!.invoke(null) as String
}
companion object {
//Required for org.jetbrains.kotlin.codegen.BlackBoxCodegenTestGenerated.FullJdk#testClasspath
val JDK_EXT_JARS_CLASS_LOADER: ClassLoader
init {
val javaHome = System.getProperty("java.home")
val extFolder = File(javaHome + "/lib/ext/")
println(extFolder.canonicalPath)
val listFiles = extFolder.listFiles()
val additionalJars = listFiles?.filter { it.name.endsWith(".jar") }?.map { it.toURI().toURL() } ?: emptyList()
JDK_EXT_JARS_CLASS_LOADER = URLClassLoader(additionalJars.toTypedArray(), null)
}
}
}
@@ -1,67 +0,0 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.test.clientserver
import org.jetbrains.kotlin.utils.rethrow
import java.io.File
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.net.Socket
import java.net.URL
import kotlin.test.fail
class TestProxy(val serverPort: Int, val testClass: String, val classPath: List<URL>) {
fun runTest(): String {
return Socket("localhost", serverPort).use { clientSocket ->
val output = ObjectOutputStream(clientSocket.getOutputStream())
val input = ObjectInputStream(clientSocket.getInputStream())
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())
val message = input.readObject() as MessageHeader
if (message == MessageHeader.RESULT) {
input.readObject() as String
}
else if (message == MessageHeader.ERROR) {
throw input.readObject() as Exception
}
else {
fail("Unknown message: $message")
}
} finally {
output.close()
input.close()
}
}
}
fun filterOutJdkJars(classPath: List<URL>): List<URL> {
val javaHome = System.getProperty("java.home")
val javaFolder = File(javaHome)
return classPath.filterNot {
File(it.file).startsWith(javaFolder)
}
}
}