[Test] Introduce provider of path of standard libraries jars

Before this change all paths to all libraries were hardcoded to
  `dist/kotlinc/lib/...`, which is not suitable for usages of test
  framework outside of Kotlin project
This commit is contained in:
Dmitriy Novozhilov
2022-04-07 16:11:01 +04:00
committed by teamcity
parent 648a3667e0
commit 2c6aea47b1
7 changed files with 158 additions and 31 deletions
@@ -153,6 +153,7 @@ abstract class AbstractFrontendApiTest : TestWithDisposable() {
useAdditionalService { ExpressionMarkerProvider() }
useAdditionalService(::TestKtModuleProvider)
useAdditionalService<ApplicationDisposableProvider> { ExecutionListenerBasedDisposableProvider() }
useAdditionalService<KotlinStandardLibrariesPathProvider> { StandardLibrariesPathProviderForKotlinProject }
configureTest(this)
startingArtifactFactory = { ResultingArtifact.Source() }
@@ -416,6 +416,7 @@ class CodegenTestsOnAndroidGenerator private constructor(private val pathManager
assertions = JUnit5Assertions
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
useAdditionalService<ApplicationDisposableProvider> { ExecutionListenerBasedDisposableProvider() }
useAdditionalService<KotlinStandardLibrariesPathProvider> { StandardLibrariesPathProviderForKotlinProject }
useSourcePreprocessor(*AbstractKotlinCompilerTest.defaultPreprocessors.toTypedArray())
useDirectives(*AbstractKotlinCompilerTest.defaultDirectiveContainers.toTypedArray())
class AndroidTransformingPreprocessor(testServices: TestServices) : SourceFilePreprocessor(testServices) {
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.test.backend.handlers
import junit.framework.TestCase
import org.jetbrains.kotlin.backend.common.CodegenUtil.getMemberDeclarationsToGenerate
import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil.getFileClassInfoNoResolve
import org.jetbrains.kotlin.psi.KtFile
@@ -24,13 +23,10 @@ import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.model.nameWithoutExtension
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.JvmEnvironmentConfigurator.Companion.TEST_CONFIGURATION_KIND_KEY
import org.jetbrains.kotlin.test.services.dependencyProvider
import org.jetbrains.kotlin.test.services.jvm.compiledClassesManager
import org.jetbrains.kotlin.test.services.jvm.jvmBoxMainClassProvider
import org.jetbrains.kotlin.test.services.runtimeClasspathProviders
import org.jetbrains.kotlin.test.services.sourceProviders.MainFunctionForBlackBoxTestsSourceProvider
import org.jetbrains.kotlin.test.services.sourceProviders.MainFunctionForBlackBoxTestsSourceProvider.Companion.fileContainsBoxMethod
import org.jetbrains.kotlin.test.util.KtTestUtil
@@ -297,9 +293,9 @@ open class JvmBoxRunner(testServices: TestServices) : JvmBinaryArtifactHandler(t
private fun createClassLoader(module: TestModule, classFileFactory: ClassFileFactory): GeneratedClassLoader {
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val parentClassLoader = if (configuration[TEST_CONFIGURATION_KIND_KEY]?.withReflection == true) {
ForTestCompileRuntime.runtimeAndReflectJarClassLoader()
testServices.standardLibrariesPathProvider.getRuntimeAndReflectJarClassLoader()
} else {
ForTestCompileRuntime.runtimeJarClassLoader()
testServices.standardLibrariesPathProvider.getRuntimeJarClassLoader()
}
val classpath = computeRuntimeClasspath(module)
return GeneratedClassLoader(classFileFactory, parentClassLoader, *classpath.map { it.toURI().toURL() }.toTypedArray())
@@ -43,6 +43,7 @@ abstract class AbstractKotlinCompilerTest {
assertions = JUnit5Assertions
useAdditionalService<TemporaryDirectoryManager>(::TemporaryDirectoryManagerImpl)
useAdditionalService<ApplicationDisposableProvider> { ExecutionListenerBasedDisposableProvider() }
useAdditionalService<KotlinStandardLibrariesPathProvider> { StandardLibrariesPathProviderForKotlinProject }
useSourcePreprocessor(*defaultPreprocessors.toTypedArray())
useDirectives(*defaultDirectiveContainers.toTypedArray())
configureDebugFlags()
@@ -0,0 +1,127 @@
/*
* Copyright 2010-2022 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.test.services
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import java.io.File
import java.lang.ref.SoftReference
import java.net.URL
import java.net.URLClassLoader
abstract class KotlinStandardLibrariesPathProvider : TestService {
companion object {
@Volatile
private var runtimeJarClassLoader: SoftReference<ClassLoader?> = SoftReference(null)
@Volatile
private var reflectJarClassLoader: SoftReference<ClassLoader?> = SoftReference(null)
private fun createClassLoader(vararg files: File): ClassLoader {
val urls: MutableList<URL> = ArrayList(2)
for (file in files) {
urls.add(file.toURI().toURL())
}
return URLClassLoader(urls.toTypedArray(), null)
}
}
/**
* kotlin-stdlib.jar
*/
abstract fun runtimeJarForTests(): File
/**
* kotlin-stdlib-jdk8.jar
*/
abstract fun runtimeJarForTestsWithJdk8(): File
/**
* Jar with minimal version of kotlin stdlib (may be same as runtimeJarForTests)
*/
abstract fun minimalRuntimeJarForTests(): File
/**
* kotlin-reflect.jar
*/
abstract fun reflectJarForTests(): File
/**
* kotlin-test.jar
*/
abstract fun kotlinTestJarForTests(): File
/**
* kotlin-script-runtime.jar
*/
abstract fun scriptRuntimeJarForTests(): File
/**
* kotlin-annotations-jvm.jar
*/
abstract fun jvmAnnotationsForTests(): File
fun getRuntimeJarClassLoader(): ClassLoader = synchronized(this) {
var loader = runtimeJarClassLoader.get()
if (loader == null) {
loader = createClassLoader(
runtimeJarForTests(),
scriptRuntimeJarForTests(),
kotlinTestJarForTests()
)
runtimeJarClassLoader = SoftReference(loader)
}
loader
}
fun getRuntimeAndReflectJarClassLoader(): ClassLoader = synchronized(this) {
var loader = reflectJarClassLoader.get()
if (loader == null) {
loader = createClassLoader(
runtimeJarForTests(),
reflectJarForTests(),
scriptRuntimeJarForTests(),
kotlinTestJarForTests())
reflectJarClassLoader = SoftReference(loader)
}
loader
}
}
object StandardLibrariesPathProviderForKotlinProject : KotlinStandardLibrariesPathProvider() {
override fun runtimeJarForTests(): File = ForTestCompileRuntime.runtimeJarForTests()
override fun runtimeJarForTestsWithJdk8(): File = ForTestCompileRuntime.runtimeJarForTestsWithJdk8()
override fun minimalRuntimeJarForTests(): File = ForTestCompileRuntime.minimalRuntimeJarForTests()
override fun reflectJarForTests(): File = ForTestCompileRuntime.reflectJarForTests()
override fun kotlinTestJarForTests(): File = ForTestCompileRuntime.kotlinTestJarForTests()
override fun scriptRuntimeJarForTests(): File = ForTestCompileRuntime.scriptRuntimeJarForTests()
override fun jvmAnnotationsForTests(): File = ForTestCompileRuntime.jvmAnnotationsForTests()
}
object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider() {
const val KOTLIN_STDLIB_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib"
const val KOTLIN_STDLIB_JDK8_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib-jdk8"
const val KOTLIN_REFLECT_PROP = "org.jetbrains.kotlin.test.kotlin-reflect"
const val KOTLIN_TEST_PROP = "org.jetbrains.kotlin.test.kotlin-test"
const val KOTLIN_SCRIPT_RUNTIME_PROP = "org.jetbrains.kotlin.test.kotlin-script-runtime"
const val KOTLIN_ANNOTATIONS_JVM_PROP = "org.jetbrains.kotlin.test.kotlin-annotations-jvm"
private fun getFile(propertyName: String): File {
return System.getProperty(propertyName)
?.let(::File)
?.takeIf { it.exists() }
?: error("Property $propertyName is not set or file under it not found")
}
override fun runtimeJarForTests(): File = getFile(KOTLIN_STDLIB_PROP)
override fun runtimeJarForTestsWithJdk8(): File = getFile(KOTLIN_STDLIB_JDK8_PROP)
override fun minimalRuntimeJarForTests(): File = getFile(KOTLIN_STDLIB_PROP)
override fun reflectJarForTests(): File = getFile(KOTLIN_REFLECT_PROP)
override fun kotlinTestJarForTests(): File = getFile(KOTLIN_TEST_PROP)
override fun scriptRuntimeJarForTests(): File = getFile(KOTLIN_SCRIPT_RUNTIME_PROP)
override fun jvmAnnotationsForTests(): File = getFile(KOTLIN_ANNOTATIONS_JVM_PROP)
}
val TestServices.standardLibrariesPathProvider: KotlinStandardLibrariesPathProvider by TestServices.testServiceAccessor()
@@ -14,7 +14,6 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
import org.jetbrains.kotlin.cli.jvm.addModularRootIfNotNull
import org.jetbrains.kotlin.cli.jvm.config.*
import org.jetbrains.kotlin.cli.jvm.configureStandardLibs
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.JVMConfigurationKeys
@@ -104,26 +103,6 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
else -> error("Too many jdk kinds passed: ${jdkKinds.joinToArrayString()}")
}
}
fun getLibraryFilesExceptRealRuntime(configurationKind: ConfigurationKind, directives: RegisteredDirectives): List<File> {
val files = mutableListOf<File>()
if (configurationKind.withRuntime) {
files.add(ForTestCompileRuntime.kotlinTestJarForTests())
} else if (configurationKind.withMockRuntime) {
files.add(ForTestCompileRuntime.minimalRuntimeJarForTests())
files.add(ForTestCompileRuntime.scriptRuntimeJarForTests())
}
if (configurationKind.withReflection) {
files.add(ForTestCompileRuntime.reflectJarForTests())
}
files.add(KtTestUtil.getAnnotationsJar())
if (JvmEnvironmentConfigurationDirectives.STDLIB_JDK8 in directives) {
files.add(ForTestCompileRuntime.runtimeJarForTestsWithJdk8())
}
files.add(KtTestUtil.getAnnotationsJar())
return files
}
}
override val directiveContainers: List<DirectivesContainer>
@@ -332,7 +311,7 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
val modulePath = buildList {
addAll(configuration.jvmModularRoots.map { it.absolutePath })
if (configurationKind.withRuntime) {
add(ForTestCompileRuntime.runtimeJarForTests().path)
add(testServices.standardLibrariesPathProvider.runtimeJarForTests().path)
}
}
return MockLibraryUtil.compileLibraryToJar(
@@ -393,4 +372,26 @@ class JvmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfig
testServices.compiledClassesManager.getCompiledJavaDirForModule(friendModule)
)
}
private fun getLibraryFilesExceptRealRuntime(configurationKind: ConfigurationKind, directives: RegisteredDirectives): List<File> {
val provider = testServices.standardLibrariesPathProvider
val files = mutableListOf<File>()
if (configurationKind.withRuntime) {
files.add(provider.kotlinTestJarForTests())
} else if (configurationKind.withMockRuntime) {
files.add(provider.minimalRuntimeJarForTests())
files.add(provider.scriptRuntimeJarForTests())
}
if (configurationKind.withReflection) {
files.add(provider.reflectJarForTests())
}
files.add(KtTestUtil.getAnnotationsJar())
if (JvmEnvironmentConfigurationDirectives.STDLIB_JDK8 in directives) {
files.add(provider.runtimeJarForTestsWithJdk8())
}
files.add(KtTestUtil.getAnnotationsJar())
return files
}
}
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.test.services.configuration
import org.jetbrains.kotlin.cli.jvm.addModularRootIfNotNull
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.load.java.*
import org.jetbrains.kotlin.name.FqName
@@ -27,6 +26,7 @@ import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
import org.jetbrains.kotlin.test.services.JUnit5Assertions
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.standardLibrariesPathProvider
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.File
import kotlin.io.path.createTempDirectory
@@ -92,7 +92,7 @@ open class JvmForeignAnnotationsConfigurator(testServices: TestServices) : Envir
useJava11 = useJava11ToCompileIncludedJavaFiles
)
configuration.addModularRootIfNotNull(useJava11ToCompileIncludedJavaFiles, "java9_annotations", foreignAnnotationsJar)
configuration.addJvmClasspathRoot(ForTestCompileRuntime.jvmAnnotationsForTests())
configuration.addJvmClasspathRoot(testServices.standardLibrariesPathProvider.jvmAnnotationsForTests())
if (JvmEnvironmentConfigurationDirectives.WITH_JSR305_TEST_ANNOTATIONS in registeredDirectives) {
val jsr305AnnotationsDir = createTempDirectory().toFile().also {