[JS Test] Introduce tests for loading metadata produced by JS compiler

This commit is contained in:
Dmitriy Novozhilov
2023-05-31 12:43:51 +03:00
committed by Space Team
parent 2290a096d1
commit 7eca772ec2
13 changed files with 3957 additions and 120 deletions
@@ -7,9 +7,13 @@ package org.jetbrains.kotlin.test
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import org.jetbrains.kotlin.backend.common.CommonKLibResolver
import org.jetbrains.kotlin.cli.common.SessionWithSources
import org.jetbrains.kotlin.cli.common.prepareJsSessions
import org.jetbrains.kotlin.cli.common.prepareJvmSessions
import org.jetbrains.kotlin.cli.jvm.compiler.VfsBasedProjectEnvironment
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.BinaryModuleData
import org.jetbrains.kotlin.fir.DependencyListForCliModule
@@ -19,31 +23,119 @@ import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
import org.jetbrains.kotlin.fir.renderer.FirRenderer
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isJs
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.test.backend.handlers.JvmBinaryArtifactHandler
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.PLATFORM_DEPENDANT_METADATA
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.LANGUAGE_VERSION
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.frontend.fir.getAllJsDependenciesPaths
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.util.trimTrailingWhitespacesAndRemoveRedundantEmptyLinesAtTheEnd
import org.jetbrains.kotlin.test.utils.MultiModuleInfoDumper
import org.jetbrains.kotlin.test.utils.withExtension
import org.jetbrains.kotlin.util.DummyLogger
import org.jetbrains.kotlin.utils.addToStdlib.shouldNotBeCalled
import java.io.File
class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactHandler(testServices) {
class JvmLoadedMetadataDumpHandler(testServices: TestServices) : AbstractLoadedMetadataDumpHandler<BinaryArtifacts.Jvm>(
testServices,
ArtifactKinds.Jvm
) {
override val targetPlatform: TargetPlatform
get() = JvmPlatforms.defaultJvmPlatform
override val platformAnalyzerServices: PlatformDependentAnalyzerServices
get() = JvmPlatformAnalyzerServices
override val dependencyKind: DependencyKind
get() = DependencyKind.Binary
override fun prepareSessions(
module: TestModule,
configuration: CompilerConfiguration,
environment: VfsBasedProjectEnvironment,
moduleName: Name,
libraryList: DependencyListForCliModule,
): List<SessionWithSources<KtFile>> {
return prepareJvmSessions(
files = emptyList(),
configuration, environment, moduleName,
extensionRegistrars = emptyList(),
environment.getSearchScopeForProjectLibraries(),
libraryList,
isCommonSource = { false },
fileBelongsToModule = { _, _ -> false },
createProviderAndScopeForIncrementalCompilation = { null }
)
}
}
class KlibLoadedMetadataDumpHandler(testServices: TestServices) : AbstractLoadedMetadataDumpHandler<BinaryArtifacts.KLib>(
testServices,
ArtifactKinds.KLib
) {
override val targetPlatform: TargetPlatform
get() = JsPlatforms.defaultJsPlatform
override val platformAnalyzerServices: PlatformDependentAnalyzerServices
get() = JsPlatformAnalyzerServices
override val dependencyKind: DependencyKind
get() = DependencyKind.KLib
override fun prepareSessions(
module: TestModule,
configuration: CompilerConfiguration,
environment: VfsBasedProjectEnvironment,
moduleName: Name,
libraryList: DependencyListForCliModule,
): List<SessionWithSources<KtFile>> {
val libraries = getAllJsDependenciesPaths(module, testServices)
val resolvedLibraries = CommonKLibResolver.resolve(libraries, DummyLogger).getFullResolvedList()
return prepareJsSessions(
files = emptyList(),
configuration,
moduleName,
resolvedLibraries.map { it.library },
libraryList,
extensionRegistrars = emptyList(),
isCommonSource = { false },
fileBelongsToModule = { _, _ -> false },
lookupTracker = null,
icData = null
)
}
}
abstract class AbstractLoadedMetadataDumpHandler<A : ResultingArtifact.Binary<A>>(
testServices: TestServices,
override val artifactKind: BinaryKind<A>
) : BinaryArtifactHandler<A>(
testServices,
artifactKind,
failureDisablesNextSteps = false,
doNotRunIfThereWerePreviousFailures = false
) {
private val dumper: MultiModuleInfoDumper = MultiModuleInfoDumper()
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
override val directiveContainers: List<DirectivesContainer>
get() = listOf(FirDiagnosticsDirectives)
override fun processModule(module: TestModule, info: A) {
if (testServices.loadedMetadataSuppressionDirective in module.directives) return
val languageVersion = module.directives.singleOrZeroValue(LANGUAGE_VERSION)
val languageVersionSettings = if (languageVersion != null) {
@@ -51,10 +143,11 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
} else {
LanguageVersionSettingsImpl.DEFAULT
}
val emptyModule = TestModule(
name = "empty", JvmPlatforms.defaultJvmPlatform, TargetBackend.JVM_IR, FrontendKinds.FIR,
BackendKinds.IrBackend, ArtifactKinds.Jvm, files = emptyList(),
allDependencies = listOf(DependencyDescription(module.name, DependencyKind.Binary, DependencyRelation.RegularDependency)),
name = "empty", module.targetPlatform, module.targetBackend, FrontendKinds.FIR,
BackendKinds.IrBackend, module.binaryKind, files = emptyList(),
allDependencies = listOf(DependencyDescription(module.name, dependencyKind, DependencyRelation.RegularDependency)),
RegisteredDirectives.Empty, languageVersionSettings
)
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(emptyModule)
@@ -63,20 +156,22 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL),
testServices.compilerConfigurationProvider.getPackagePartProviderFactory(emptyModule)
)
val moduleName = Name.identifier(emptyModule.name)
val binaryModuleData = BinaryModuleData.initialize(
Name.identifier(emptyModule.name),
JvmPlatforms.defaultJvmPlatform,
JvmPlatformAnalyzerServices
moduleName,
targetPlatform,
platformAnalyzerServices
)
val session = prepareJvmSessions(
files = emptyList<KtFile>(),
configuration, environment, Name.identifier(emptyModule.name),
extensionRegistrars = emptyList(),
environment.getSearchScopeForProjectLibraries(),
DependencyListForCliModule.build(binaryModuleData),
isCommonSource = { false },
fileBelongsToModule = { _, _ -> false },
createProviderAndScopeForIncrementalCompilation = { null }
val libraryList = FirFrontendFacade.initializeLibraryList(
emptyModule, binaryModuleData, targetPlatform, configuration, testServices
)
val session = prepareSessions(
emptyModule,
configuration,
environment,
moduleName,
libraryList
).single().session
val packageFqName = FqName("test")
@@ -84,42 +179,104 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
.append(collectPackageContent(session, packageFqName, extractNames(module, packageFqName)))
}
@Suppress("warnings")
protected abstract val targetPlatform: TargetPlatform
protected abstract val platformAnalyzerServices: PlatformDependentAnalyzerServices
protected abstract val dependencyKind: DependencyKind
protected abstract fun prepareSessions(
module: TestModule,
configuration: CompilerConfiguration,
environment: VfsBasedProjectEnvironment,
moduleName: Name,
libraryList: DependencyListForCliModule,
): List<SessionWithSources<KtFile>>
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
if (dumper.isEmpty()) return
val testDataFile = testServices.moduleStructure.originalTestDataFiles.first()
val frontendKind = testServices.defaultsProvider.defaultFrontend
val commonExtension = ".fir.txt"
val (specificExtension, otherSpecificExtension) = when (testServices.defaultsProvider.defaultFrontend) {
val (specificExtension, otherSpecificExtension) = when (frontendKind) {
FrontendKinds.ClassicFrontend -> ".fir.k1.txt" to ".fir.k2.txt"
FrontendKinds.FIR -> ".fir.k2.txt" to ".fir.k1.txt"
else -> shouldNotBeCalled()
}
val commonFirDump = testDataFile.withExtension(commonExtension)
val specificFirDump = testDataFile.withExtension(specificExtension)
val expectedFile = when {
commonFirDump.exists() -> commonFirDump
else -> specificFirDump
}
val targetPlatform = testServices.defaultsProvider.defaultPlatform
if (PLATFORM_DEPENDANT_METADATA in testServices.moduleStructure.allDirectives) {
val platformExtension = specificExtension.replace(".txt", "${targetPlatform.suffix}.txt")
val otherPlatformExtension = specificExtension.replace(".txt", "${targetPlatform.oppositeSuffix}.txt")
val actualText = dumper.generateResultingDump()
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
val expectedFile = testDataFile.withExtension(platformExtension)
val actualText = dumper.generateResultingDump()
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
if (commonFirDump.exists() && specificFirDump.exists()) {
assertions.fail {
"""
val checks = listOf(commonExtension, specificExtension, otherSpecificExtension).map { extension ->
{
val baseFile = testDataFile.withExtension(extension)
assertions.assertFalse(baseFile.exists()) {
"Base file $baseFile exists in presence of $PLATFORM_DEPENDANT_METADATA directive. Please remove file or directive"
}
}
}
assertions.assertAll(checks)
val secondFile = testDataFile.withExtension(otherPlatformExtension)
val common = testDataFile.withExtension(specificExtension)
checkDumpsIdentity(
testDataFile, expectedFile, secondFile, common,
postProcessTestData = { it.replace("// $PLATFORM_DEPENDANT_METADATA\n", "") }
)
} else {
val commonFirDump = testDataFile.withExtension(commonExtension)
val specificFirDump = testDataFile.withExtension(specificExtension)
val expectedFile = when {
commonFirDump.exists() -> commonFirDump
else -> specificFirDump
}
val actualText = dumper.generateResultingDump()
assertions.assertEqualsToFile(expectedFile, actualText, message = { "Content is not equal" })
if (commonFirDump.exists() && specificFirDump.exists()) {
assertions.fail {
"""
Common dump ${commonFirDump.name} and specific ${specificFirDump.name} exist at the same time
Please remove ${specificFirDump.name}
""".trimIndent()
}
}
if (!commonFirDump.exists()) {
val otherFirDump = testDataFile.withExtension(otherSpecificExtension)
checkDumpsIdentity(testDataFile, specificFirDump, otherFirDump, commonFirDump)
}
}
if (!commonFirDump.exists()) {
val otherFirDump = testDataFile.withExtension(otherSpecificExtension)
checkK1AndK2DumpsIdentity(specificFirDump, otherFirDump, commonFirDump)
}
}
private fun checkK1AndK2DumpsIdentity(file1: File, file2: File, commonFile: File) {
private val TargetPlatform.suffix: String
get() = when {
isJvm() -> ".jvm"
isJs() -> ".klib"
else -> error("Unsupported platform: $this")
}
private val TargetPlatform.oppositeSuffix: String
get() = when {
isJvm() -> ".klib"
isJs() -> ".jvm"
else -> error("Unsupported platform: $this")
}
private fun checkDumpsIdentity(
testDataFile: File,
file1: File,
file2: File,
commonFile: File,
postProcessTestData: ((String) -> String)? = null
) {
if (!file1.exists() || !file2.exists()) return
val dump1 = file1.readText().trimTrailingWhitespacesAndRemoveRedundantEmptyLinesAtTheEnd()
val dump2 = file2.readText().trimTrailingWhitespacesAndRemoveRedundantEmptyLinesAtTheEnd()
@@ -127,6 +284,9 @@ class LoadedMetadataDumpHandler(testServices: TestServices) : JvmBinaryArtifactH
commonFile.writeText(dump1)
file1.delete()
file2.delete()
if (postProcessTestData != null) {
testDataFile.writeText(postProcessTestData(testDataFile.readText()))
}
assertions.fail {
"""
Files ${file1.name} and ${file2.name} are identical
@@ -37,7 +37,7 @@ abstract class AbstractFirLoadCompiledJvmKotlinTestBase<F : ResultingArtifact.Fr
)
configureJvmArtifactsHandlersStep {
useHandlers(::LoadedMetadataDumpHandler)
useHandlers(::JvmLoadedMetadataDumpHandler)
}
forTestsMatching("compiler/testData/loadJava/compiledKotlinWithStdlib/*") {
@@ -81,6 +81,13 @@ object FirDiagnosticsDirectives : SimpleDirectivesContainer() {
Directive must contain description of ignoring in argument
""".trimIndent()
)
val PLATFORM_DEPENDANT_METADATA by directive(
description = """
Generate separate dumps for JVM and JS load compiled kotlin tests
See AbstractLoadedMetadataDumpHandler
"""
)
}
fun TestConfigurationBuilder.configureFirParser(parser: FirParser) {
@@ -136,7 +136,7 @@ open class FirFrontendFacade(
val compilerConfigurationProvider = testServices.compilerConfigurationProvider
val configuration = compilerConfigurationProvider.getCompilerConfiguration(mainModule)
val libraryList = initializeLibraryList(mainModule, binaryModuleData, targetPlatform, configuration)
val libraryList = initializeLibraryList(mainModule, binaryModuleData, targetPlatform, configuration, testServices)
val moduleInfoProvider = testServices.firModuleInfoProvider
val moduleDataMap = mutableMapOf<TestModule, FirModuleData>()
@@ -163,38 +163,6 @@ open class FirFrontendFacade(
return moduleDataMap to libraryList.moduleDataProvider
}
private fun initializeLibraryList(
mainModule: TestModule,
binaryModuleData: BinaryModuleData,
targetPlatform: TargetPlatform,
configuration: CompilerConfiguration,
): DependencyListForCliModule {
return DependencyListForCliModule.build(binaryModuleData) {
when {
targetPlatform.isCommon() || targetPlatform.isJvm() -> {
dependencies(configuration.jvmModularRoots.map { it.toPath() })
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
}
targetPlatform.isJs() -> {
val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
}
targetPlatform.isNative() -> {
val runtimeKlibsPaths = NativeEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
}
else -> error("Unsupported")
}
}
}
private fun createLibrarySession(
module: TestModule,
project: Project,
@@ -414,4 +382,39 @@ open class FirFrontendFacade(
else -> error("Unsupported")
}
}
companion object {
fun initializeLibraryList(
mainModule: TestModule,
binaryModuleData: BinaryModuleData,
targetPlatform: TargetPlatform,
configuration: CompilerConfiguration,
testServices: TestServices
): DependencyListForCliModule {
return DependencyListForCliModule.build(binaryModuleData) {
when {
targetPlatform.isCommon() || targetPlatform.isJvm() -> {
dependencies(configuration.jvmModularRoots.map { it.toPath() })
dependencies(configuration.jvmClasspathRoots.map { it.toPath() })
friendDependencies(configuration[JVMConfigurationKeys.FRIEND_PATHS] ?: emptyList())
}
targetPlatform.isJs() -> {
val runtimeKlibsPaths = JsEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
}
targetPlatform.isNative() -> {
val runtimeKlibsPaths = NativeEnvironmentConfigurator.getRuntimePathsForModule(mainModule, testServices)
val (transitiveLibraries, friendLibraries) = getTransitivesAndFriends(mainModule, testServices)
dependencies(runtimeKlibsPaths.map { Paths.get(it).toAbsolutePath() })
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
}
else -> error("Unsupported")
}
}
}
}
}
@@ -24,6 +24,9 @@ object FrontendKinds {
}
}
val FrontendKind<*>.isFir: Boolean
get() = this == FrontendKinds.FIR
object BackendKinds {
object ClassicBackend : BackendKind<ClassicBackendInput>("ClassicBackend")
object IrBackend : BackendKind<IrBackendInput>("IrBackend")
@@ -72,6 +72,21 @@ abstract class KotlinStandardLibrariesPathProvider : TestService {
*/
abstract fun getAnnotationsJar(): File
/**
* kotlin-stdlib-js.jar
*/
abstract fun fullJsStdlib(): File
/**
* Jar with minimal version of kotlin stdlib JS (may be same as fullJsStdlib)
*/
abstract fun defaultJsStdlib(): File
/**
* kotlin-test-js.jar
*/
abstract fun kotlinTestJsKLib(): File
fun getRuntimeJarClassLoader(): ClassLoader = synchronized(this) {
var loader = runtimeJarClassLoader.get()
if (loader == null) {
@@ -108,13 +123,28 @@ object StandardLibrariesPathProviderForKotlinProject : KotlinStandardLibrariesPa
override fun scriptRuntimeJarForTests(): File = ForTestCompileRuntime.scriptRuntimeJarForTests()
override fun jvmAnnotationsForTests(): File = ForTestCompileRuntime.jvmAnnotationsForTests()
override fun getAnnotationsJar(): File = KtTestUtil.getAnnotationsJar()
override fun fullJsStdlib(): File = extractFromPropertyFirst("kotlin.js.full.stdlib.path") { "kotlin-stdlib-js.jar".dist() }
override fun defaultJsStdlib(): File = extractFromPropertyFirst("kotlin.js.reduced.stdlib.path") { "kotlin-stdlib-js.jar".dist() }
override fun kotlinTestJsKLib(): File = extractFromPropertyFirst("kotlin.js.kotlin.test.path") { "kotlin-test-js.jar".dist() }
private inline fun extractFromPropertyFirst(prop: String, onMissingProperty: () -> String): File {
val path = System.getProperty(prop, null) ?: onMissingProperty()
return File(path)
}
private fun String.dist(): String {
return "dist/kotlinc/lib/$this"
}
}
object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPathProvider() {
const val KOTLIN_STDLIB_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib"
const val KOTLIN_STDLIB_JS_PROP = "org.jetbrains.kotlin.test.kotlin-stdlib-js"
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_TEST_JS_PROP = "org.jetbrains.kotlin.test.kotlin-test-js"
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"
@@ -133,6 +163,9 @@ object EnvironmentBasedStandardLibrariesPathProvider : KotlinStandardLibrariesPa
override fun scriptRuntimeJarForTests(): File = getFile(KOTLIN_SCRIPT_RUNTIME_PROP)
override fun jvmAnnotationsForTests(): File = getFile(KOTLIN_ANNOTATIONS_JVM_PROP)
override fun getAnnotationsJar(): File = getFile(KOTLIN_ANNOTATIONS_JVM_PROP)
override fun fullJsStdlib(): File = getFile(KOTLIN_STDLIB_JS_PROP)
override fun defaultJsStdlib(): File = getFile(KOTLIN_STDLIB_JS_PROP)
override fun kotlinTestJsKLib(): File = getFile(KOTLIN_TEST_JS_PROP)
}
val TestServices.standardLibrariesPathProvider: KotlinStandardLibrariesPathProvider by TestServices.testServiceAccessor()
@@ -154,8 +154,13 @@ class JsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigu
val needsFullIrRuntime = JsEnvironmentConfigurationDirectives.KJS_WITH_FULL_RUNTIME in module.directives ||
ConfigurationDirectives.WITH_STDLIB in module.directives
val names = if (needsFullIrRuntime) listOf("full.stdlib", "kotlin.test") else listOf("reduced.stdlib")
names.mapNotNullTo(result) { System.getProperty("kotlin.js.$it.path")?.let { File(it).absolutePath } }
val pathProvider = testServices.standardLibrariesPathProvider
if (needsFullIrRuntime) {
result += pathProvider.fullJsStdlib().absolutePath
result += pathProvider.kotlinTestJsKLib().absolutePath
} else {
result += pathProvider.defaultJsStdlib().absolutePath
}
val runtimeClasspaths = testServices.runtimeClasspathProviders.flatMap { it.runtimeClassPaths(module) }
runtimeClasspaths.mapTo(result) { it.absolutePath }
return result
+1
View File
@@ -37,6 +37,7 @@ dependencies {
testApi(projectTests(":compiler:test-infrastructure-utils"))
testApi(projectTests(":compiler:tests-compiler-utils"))
testApi(projectTests(":compiler:tests-common-new"))
testImplementation(projectTests(":compiler:fir:analysis-tests"))
testCompileOnly(project(":compiler:frontend"))
testCompileOnly(project(":compiler:cli"))
@@ -230,6 +230,11 @@ fun main(args: Array<String>) {
// testClass<AbstractFirJsSteppingTest> {
// model("debug/stepping")
// }
testClass<AbstractFirLoadK2CompiledJsKotlinTest> {
model("loadJava/compiledKotlin", extension = "kt")
model("loadJava/compiledKotlinWithStdlib", extension = "kt")
}
}
}
}
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2023 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.js.test.fir
import org.jetbrains.kotlin.js.test.converters.FirJsKlibBackendFacade
import org.jetbrains.kotlin.js.test.ir.commonConfigurationForJsCodegenTest
import org.jetbrains.kotlin.test.*
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.builders.configureKlibArtifactsHandlersStep
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.FIR_PARSER
import org.jetbrains.kotlin.test.frontend.fir.Fir2IrResultsConverter
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
abstract class AbstractFirLoadCompiledJsKotlinTestBase<F : ResultingArtifact.FrontendOutput<F>> :
AbstractKotlinCompilerWithTargetBackendTest(TargetBackend.JS_IR)
{
protected abstract val frontendKind: FrontendKind<F>
protected abstract val frontendFacade: Constructor<FrontendFacade<F>>
protected abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<F, IrBackendInput>>
override fun TestConfigurationBuilder.configuration() {
commonConfigurationForJsCodegenTest(
frontendKind,
frontendFacade,
frontendToBackendConverter,
::FirJsKlibBackendFacade,
)
configureKlibArtifactsHandlersStep {
useHandlers(::KlibLoadedMetadataDumpHandler)
}
useAfterAnalysisCheckers(::FirMetadataLoadingTestSuppressor)
}
}
open class AbstractFirLoadK2CompiledJsKotlinTest : AbstractFirLoadCompiledJsKotlinTestBase<FirOutputArtifact>() {
override val frontendKind: FrontendKind<FirOutputArtifact>
get() = FrontendKinds.FIR
override val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
get() = ::FirFrontendFacade
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>>
get() = ::Fir2IrResultsConverter
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
builder.defaultDirectives {
FIR_PARSER with FirParser.LightTree
}
}
}
@@ -56,15 +56,10 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
}
protected fun TestConfigurationBuilder.commonConfigurationForJsBlackBoxCodegenTest() {
globalDefaults {
frontend = targetFrontend
targetPlatform = JsPlatforms.defaultJsPlatform
dependencyKind = DependencyKind.Binary
}
commonConfigurationForJsCodegenTest(targetFrontend, frontendFacade, frontendToBackendConverter, backendFacade)
val pathToRootOutputDir = System.getProperty("kotlin.js.test.root.out.dir") ?: error("'kotlin.js.test.root.out.dir' is not set")
defaultDirectives {
+DiagnosticsDirectives.REPORT_ONLY_EXPLICITLY_DEFINED_DEBUG_INFO
JsEnvironmentConfigurationDirectives.PATH_TO_ROOT_OUTPUT_DIR with pathToRootOutputDir
JsEnvironmentConfigurationDirectives.PATH_TO_TEST_DIR with pathToTestDir
JsEnvironmentConfigurationDirectives.TEST_GROUP_OUTPUT_DIR_PREFIX with testGroupOutputDirPrefix
@@ -74,6 +69,11 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
if (getBoolean("kotlin.js.ir.skipRegularMode")) +JsEnvironmentConfigurationDirectives.SKIP_REGULAR_MODE
}
useAdditionalSourceProviders(
::JsAdditionalSourceProvider,
::CoroutineHelpersSourceFilesProvider,
)
forTestsNotMatching("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/*") {
defaultDirectives {
DIAGNOSTICS with "-warnings"
@@ -84,47 +84,20 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
enableMetaInfoHandler()
}
useConfigurators(
::CommonEnvironmentConfigurator,
::JsEnvironmentConfigurator,
)
useAdditionalSourceProviders(
::JsAdditionalSourceProvider,
::CoroutineHelpersSourceFilesProvider,
)
useAdditionalService(::JsLibraryProvider)
useAfterAnalysisCheckers(
::JsFailingTestSuppressor,
::BlackBoxCodegenSuppressor,
::JsArtifactsDumpHandler
)
facadeStep(frontendFacade)
classicFrontendHandlersStep {
commonClassicFrontendHandlersForCodegenTest()
useHandlers(::ClassicDiagnosticsHandler)
}
firHandlersStep {
useHandlers(::FirDiagnosticsHandler)
}
facadeStep(frontendToBackendConverter)
irHandlersStep {
configureIrHandlersStep {
useHandlers(::IrMangledNameAndSignatureDumpHandler)
}
facadeStep(backendFacade)
klibArtifactsHandlersStep()
afterBackendFacade?.let { facadeStep(it) }
facadeStep(recompileFacade)
jsArtifactsHandlersStep {
useHandlers(::JsSourceMapPathRewriter)
}
useAfterAnalysisCheckers(
::JsArtifactsDumpHandler
)
forTestsMatching("compiler/testData/codegen/box/involvesIrInterpreter/*") {
enableMetaInfoHandler()
configureKlibArtifactsHandlersStep {
@@ -136,3 +109,53 @@ abstract class AbstractJsBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendO
}
}
}
@Suppress("reformat")
fun <
R : ResultingArtifact.FrontendOutput<R>,
I : ResultingArtifact.BackendInput<I>,
A : ResultingArtifact.Binary<A>
> TestConfigurationBuilder.commonConfigurationForJsCodegenTest(
targetFrontend: FrontendKind<R>,
frontendFacade: Constructor<FrontendFacade<R>>,
frontendToBackendConverter: Constructor<Frontend2BackendConverter<R, I>>,
backendFacade: Constructor<BackendFacade<I, A>>,
) {
globalDefaults {
frontend = targetFrontend
targetPlatform = JsPlatforms.defaultJsPlatform
dependencyKind = DependencyKind.Binary
}
defaultDirectives {
+DiagnosticsDirectives.REPORT_ONLY_EXPLICITLY_DEFINED_DEBUG_INFO
}
useConfigurators(
::CommonEnvironmentConfigurator,
::JsEnvironmentConfigurator,
)
useAdditionalService(::JsLibraryProvider)
useAfterAnalysisCheckers(
::JsFailingTestSuppressor,
::BlackBoxCodegenSuppressor,
)
facadeStep(frontendFacade)
classicFrontendHandlersStep {
commonClassicFrontendHandlersForCodegenTest()
useHandlers(::ClassicDiagnosticsHandler)
}
firHandlersStep {
useHandlers(::FirDiagnosticsHandler)
}
facadeStep(frontendToBackendConverter)
irHandlersStep()
facadeStep(backendFacade)
klibArtifactsHandlersStep()
}
@@ -20,11 +20,8 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestService
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.JsEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.jsLibraryProvider
import java.io.ByteArrayOutputStream
import java.io.File
@@ -46,14 +43,14 @@ private class TestArtifactCache(val moduleName: String, val binaryAsts: MutableM
}
class JsIrIncrementalDataProvider(private val testServices: TestServices) : TestService {
private val fullRuntimeKlib: String = System.getProperty("kotlin.js.full.stdlib.path")
private val defaultRuntimeKlib = System.getProperty("kotlin.js.reduced.stdlib.path")
private val kotlinTestKLib = System.getProperty("kotlin.js.kotlin.test.path")
private val fullRuntimeKlib = testServices.standardLibrariesPathProvider.fullJsStdlib()
private val defaultRuntimeKlib = testServices.standardLibrariesPathProvider.defaultJsStdlib()
private val kotlinTestKLib = testServices.standardLibrariesPathProvider.kotlinTestJsKLib()
private val predefinedKlibHasIcCache = mutableMapOf<String, TestArtifactCache?>(
File(fullRuntimeKlib).absolutePath to null,
File(kotlinTestKLib).absolutePath to null,
File(defaultRuntimeKlib).absolutePath to null
fullRuntimeKlib.absolutePath to null,
kotlinTestKLib.absolutePath to null,
defaultRuntimeKlib.absolutePath to null
)
private val icCache: MutableMap<String, TestArtifactCache> = mutableMapOf()