[Wasm] Initial K2 support in new test infrastructure (KT-57230)

- Implement FirWasmSessionFactory
- Use new compiler test infra for Wasm K1 and K2
- Delete old Wasm compiler test infra
This commit is contained in:
Svyatoslav Kuzmich
2023-06-12 11:23:31 +02:00
parent 3e564236f9
commit 9b3237fff9
40 changed files with 52444 additions and 4295 deletions
-1
View File
@@ -672,7 +672,6 @@ tasks {
register("wasmCompilerTest") {
dependsOn(":wasm:wasm.tests:test")
dependsOn(":wasm:wasm.tests:diagnosticsTest")
// Windows WABT release requires Visual C++ Redistributable
if (!kotlinBuildProperties.isTeamcityBuild || !org.gradle.internal.os.OperatingSystem.current().isWindows) {
dependsOn(":wasm:wasm.ir:test")
@@ -41,4 +41,8 @@ fun FirSessionConfigurator.registerJsCheckers() {
fun FirSessionConfigurator.registerNativeCheckers() {
useCheckers(NativeDeclarationCheckers)
useCheckers(NativeExpressionCheckers)
}
fun FirSessionConfigurator.registerWasmCheckers() {
// TODO: Implement Wasm checkers (KT-56849)
}
@@ -0,0 +1,109 @@
/*
* Copyright 2010-2020 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.fir.session
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirVisibilityChecker
import org.jetbrains.kotlin.fir.SessionConfiguration
import org.jetbrains.kotlin.fir.analysis.FirEmptyOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.analysis.FirOverridesBackwardCompatibilityHelper
import org.jetbrains.kotlin.fir.checkers.registerWasmCheckers
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.deserialization.SingleModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirBuiltinSyntheticFunctionInterfaceProvider
import org.jetbrains.kotlin.fir.resolve.providers.impl.FirExtensionSyntheticFunctionInterfaceProvider
import org.jetbrains.kotlin.fir.scopes.FirKotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.Name
object FirWasmSessionFactory : FirAbstractSessionFactory() {
fun createModuleBasedSession(
moduleData: FirModuleData,
sessionProvider: FirProjectSessionProvider,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
lookupTracker: LookupTracker?,
icData: KlibIcData? = null,
registerExtraComponents: ((FirSession) -> Unit) = {},
init: FirSessionConfigurator.() -> Unit
): FirSession {
return createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
languageVersionSettings,
lookupTracker,
null,
init,
registerExtraComponents = { session ->
session.registerWasmSpecificComponents()
registerExtraComponents(session)
},
registerExtraCheckers = { it.registerWasmCheckers() },
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _, _ -> declaredMemberScope } },
createProviders = { session, kotlinScopeProvider, symbolProvider, generatedSymbolsProvider, syntheticFunctionInterfaceProvider, dependencies ->
listOfNotNull(
symbolProvider,
generatedSymbolsProvider,
icData?.let {
KlibIcCacheBasedSymbolProvider(
session,
SingleModuleDataProvider(moduleData),
kotlinScopeProvider,
it,
)
},
syntheticFunctionInterfaceProvider,
*dependencies.toTypedArray(),
)
}
)
}
fun createLibrarySession(
mainModuleName: Name,
resolvedLibraries: List<KotlinLibrary>,
sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings = LanguageVersionSettingsImpl.DEFAULT,
registerExtraComponents: ((FirSession) -> Unit),
): FirSession = createLibrarySession(
mainModuleName,
sessionProvider,
moduleDataProvider,
languageVersionSettings,
extensionRegistrars,
registerExtraComponents = {
it.registerWasmSpecificComponents()
registerExtraComponents(it)
},
createKotlinScopeProvider = { FirKotlinScopeProvider { _, declaredMemberScope, _, _, _ -> declaredMemberScope } },
createProviders = { session, builtinsModuleData, kotlinScopeProvider ->
listOfNotNull(
KlibBasedSymbolProvider(session, moduleDataProvider, kotlinScopeProvider, resolvedLibraries),
FirBuiltinSyntheticFunctionInterfaceProvider(session, builtinsModuleData, kotlinScopeProvider),
FirExtensionSyntheticFunctionInterfaceProvider.createIfNeeded(session, builtinsModuleData, kotlinScopeProvider),
)
}
)
@OptIn(SessionConfiguration::class)
fun FirSession.registerWasmSpecificComponents() {
register(FirVisibilityChecker::class, FirVisibilityChecker.Default)
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
register(FirOverridesBackwardCompatibilityHelper::class, FirEmptyOverridesBackwardCompatibilityHelper)
}
}
@@ -10,11 +10,13 @@ import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.isJs
import org.jetbrains.kotlin.platform.isWasm
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.konan.isNative
import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices
import org.jetbrains.kotlin.resolve.konan.platform.NativePlatformAnalyzerServices
import org.jetbrains.kotlin.wasm.resolve.WasmPlatformAnalyzerServices
import java.io.File
/**
@@ -39,6 +41,7 @@ fun TargetPlatform.getAnalyzerServices(): PlatformDependentAnalyzerServices {
isJs() -> JsPlatformAnalyzerServices
isNative() -> NativePlatformAnalyzerServices
isCommon() -> CommonPlatformAnalyzerServices
isWasm() -> WasmPlatformAnalyzerServices
else -> error("Unknown target platform: $this")
}
}
@@ -52,3 +52,14 @@ abstract class NativeBinaryArtifactHandler(
failureDisablesNextSteps,
doNotRunIfThereWerePreviousFailures
)
abstract class WasmBinaryArtifactHandler(
testServices: TestServices,
failureDisablesNextSteps: Boolean = false,
doNotRunIfThereWerePreviousFailures: Boolean = false
) : BinaryArtifactHandler<BinaryArtifacts.Wasm>(
testServices,
ArtifactKinds.Wasm,
failureDisablesNextSteps,
doNotRunIfThereWerePreviousFailures
)
@@ -97,6 +97,14 @@ class JsIrInterpreterDumpHandler(testServices: TestServices) : IrInterpreterDump
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
}
class WasmIrInterpreterDumpHandler(testServices: TestServices) : IrInterpreterDumpHandler, WasmBinaryArtifactHandler(testServices) {
override fun processModule(module: TestModule, info: BinaryArtifacts.Wasm) {
processModule(module)
}
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
}
class KlibInterpreterDumpHandler(testServices: TestServices) : IrInterpreterDumpHandler, KlibArtifactHandler(testServices) {
override fun processModule(module: TestModule, info: BinaryArtifacts.KLib) {
if (JsEnvironmentConfigurator.isMainModule(module, testServices)) return
@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.test.model.BackendKinds
import org.jetbrains.kotlin.test.model.ResultingArtifact
// IR backend (JVM, JS, Native)
// IR backend (JVM, JS, Native, Wasm)
sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
override val kind: BackendKinds.IrBackend
get() = BackendKinds.IrBackend
@@ -84,6 +84,21 @@ sealed class IrBackendInput : ResultingArtifact.BackendInput<IrBackendInput>() {
val serializeSingleFile: (KtSourceFile, IrActualizedResult?) -> ProtoBuf.PackageFragment,
) : IrBackendInput()
class WasmBackendInput(
override val irModuleFragment: IrModuleFragment,
override val dependentIrModuleFragments: List<IrModuleFragment>,
override val irPluginContext: IrPluginContext,
val sourceFiles: List<KtSourceFile>,
val icData: List<KotlinFileSerializedData>,
val expectDescriptorToSymbol: MutableMap<DeclarationDescriptor, IrSymbol>, // TODO: abstract from descriptors
override val diagnosticReporter: BaseDiagnosticsCollector,
val hasErrors: Boolean,
override val descriptorMangler: KotlinMangler.DescriptorMangler,
override val irMangler: KotlinMangler.IrMangler,
override val firMangler: FirMangler?,
val serializeSingleFile: (KtSourceFile, IrActualizedResult?) -> ProtoBuf.PackageFragment,
) : IrBackendInput()
class JvmIrBackendInput(
val state: GenerationState,
val codegenFactory: JvmIrCodegenFactory,
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.test.builders.CompilerStepsNames.JS_ARTIFACTS_HANDLE
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.JVM_ARTIFACTS_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.KLIB_ARTIFACTS_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.RAW_IR_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.builders.CompilerStepsNames.WASM_ARTIFACTS_HANDLERS_STEP_NAME
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2ClassicBackendConverter
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2IrConverter
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
@@ -38,6 +39,7 @@ object CompilerStepsNames {
const val JVM_BACKEND_STEP_NAME = "jvm backend"
const val JVM_ARTIFACTS_HANDLERS_STEP_NAME = "jvm artifacts handlers"
const val JS_ARTIFACTS_HANDLERS_STEP_NAME = "js artifacts handlers"
const val WASM_ARTIFACTS_HANDLERS_STEP_NAME = "wasm artifacts handlers"
const val KLIB_ARTIFACTS_HANDLERS_STEP_NAME = "klib artifacts handlers"
}
@@ -105,6 +107,12 @@ inline fun TestConfigurationBuilder.jsArtifactsHandlersStep(
namedHandlersStep(JS_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Js, init)
}
inline fun TestConfigurationBuilder.wasmArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Wasm>.() -> Unit = {}
) {
namedHandlersStep(WASM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Wasm, init)
}
inline fun TestConfigurationBuilder.klibArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.KLib>.() -> Unit = {}
) {
@@ -142,6 +150,12 @@ inline fun TestConfigurationBuilder.configureJsArtifactsHandlersStep(
configureNamedHandlersStep(JS_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Js, init)
}
inline fun TestConfigurationBuilder.configureWasmArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.Wasm>.() -> Unit = {}
) {
configureNamedHandlersStep(WASM_ARTIFACTS_HANDLERS_STEP_NAME, ArtifactKinds.Wasm, init)
}
inline fun TestConfigurationBuilder.configureKlibArtifactsHandlersStep(
init: HandlersStepBuilder<BinaryArtifacts.KLib>.() -> Unit = {}
) {
@@ -0,0 +1,33 @@
/*
* Copyright 2010-2020 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.directives
import org.jetbrains.kotlin.test.directives.model.DirectiveApplicability
import org.jetbrains.kotlin.test.directives.model.SimpleDirectivesContainer
object WasmEnvironmentConfigurationDirectives : SimpleDirectivesContainer() {
val RUN_UNIT_TESTS by directive(
description = "Run kotlin.test unit tests (function marked with @Test)",
)
// Next directives are used only inside test system and must not be present in test file
val PATH_TO_TEST_DIR by stringDirective(
description = "Specify the path to directory with test files. " +
"This path is used to copy hierarchy from test file to test dir and use the same hierarchy in output dir.",
applicability = DirectiveApplicability.Global
)
val PATH_TO_ROOT_OUTPUT_DIR by stringDirective(
description = "Specify the path to output directory, where all artifacts will be stored",
applicability = DirectiveApplicability.Global
)
val TEST_GROUP_OUTPUT_DIR_PREFIX by stringDirective(
description = "Specify the prefix directory for output directory that will contains artifacts",
applicability = DirectiveApplicability.Global
)
}
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtPsiSourceFile
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.js.klib.TopDownAnalyzerFacadeForJSIR
import org.jetbrains.kotlin.cli.js.klib.TopDownAnalyzerFacadeForWasm
import org.jetbrains.kotlin.cli.js.klib.generateIrForKlibSerialization
import org.jetbrains.kotlin.codegen.ClassBuilderFactories
import org.jetbrains.kotlin.codegen.CodegenFactory
@@ -33,6 +34,7 @@ import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfigurator
class ClassicFrontend2IrConverter(
testServices: TestServices
@@ -48,6 +50,7 @@ class ClassicFrontend2IrConverter(
return when (module.targetBackend) {
TargetBackend.JVM_IR -> transformToJvmIr(module, inputArtifact)
TargetBackend.JS_IR, TargetBackend.JS_IR_ES6 -> transformToJsIr(module, inputArtifact)
TargetBackend.WASM -> transformToWasmIr(module, inputArtifact)
else -> testServices.assertions.fail { "Target backend ${module.targetBackend} not supported for transformation into IR" }
}
}
@@ -125,4 +128,49 @@ class ClassicFrontend2IrConverter(
metadataSerializer.serializeScope(file, analysisResult.bindingContext, moduleFragment.descriptor)
}
}
private fun transformToWasmIr(module: TestModule, inputArtifact: ClassicFrontendOutputArtifact): IrBackendInput {
val (psiFiles, analysisResult, project, _) = inputArtifact
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val verifySignatures = JsEnvironmentConfigurationDirectives.SKIP_MANGLE_VERIFICATION !in module.directives
val sourceFiles = psiFiles.values.toList()
val icData = configuration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList()
val expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
val (moduleFragment, pluginContext) = generateIrForKlibSerialization(
project,
sourceFiles,
configuration,
analysisResult,
sortDependencies(WasmEnvironmentConfigurator.getAllDependenciesMappingFor(module, testServices)),
icData,
expectDescriptorToSymbol,
IrFactoryImpl,
verifySignatures
) {
testServices.libraryProvider.getDescriptorByCompiledLibrary(it)
}
val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT
val hasErrors = TopDownAnalyzerFacadeForWasm.checkForErrors(sourceFiles, analysisResult.bindingContext, errorPolicy)
val metadataSerializer = KlibMetadataIncrementalSerializer(configuration, project, hasErrors)
return IrBackendInput.WasmBackendInput(
moduleFragment,
dependentIrModuleFragments = emptyList(),
pluginContext,
sourceFiles.map(::KtPsiSourceFile),
icData,
expectDescriptorToSymbol = expectDescriptorToSymbol,
diagnosticReporter = DiagnosticReporterFactory.createReporter(),
hasErrors,
descriptorMangler = (pluginContext.symbolTable as SymbolTable).signaturer.mangler,
irMangler = JsManglerIr,
firMangler = null,
) { file, _ ->
metadataSerializer.serializeScope(file, analysisResult.bindingContext, moduleFragment.descriptor)
}
}
}
@@ -346,12 +346,10 @@ class ClassicFrontendFacade(
dependencyDescriptors: List<ModuleDescriptor>,
friendsDescriptors: List<ModuleDescriptor>,
): AnalysisResult {
val needsKotlinTest = ConfigurationDirectives.WITH_STDLIB in module.directives
val runtimeKlibsNames =
listOfNotNull(
System.getProperty("kotlin.wasm.stdlib.path")!!,
System.getProperty("kotlin.wasm.kotlin.test.path")!!.takeIf { needsKotlinTest }
System.getProperty("kotlin.wasm.kotlin.test.path")!!
).map {
File(it).absolutePath
}
@@ -0,0 +1,228 @@
/*
* Copyright 2010-2020 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.frontend.fir
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
import org.jetbrains.kotlin.backend.common.serialization.signature.IdSignatureDescriptor
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.constant.EvaluatedConstTracker
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.fir.AbstractFirAnalyzerFacade
import org.jetbrains.kotlin.fir.FirAnalyzerFacade
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.js.FirJsKotlinMangler
import org.jetbrains.kotlin.fir.backend.jvm.Fir2IrJvmSpecialAnnotationSymbolProvider
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.serialization.FirKLibSerializerExtension
import org.jetbrains.kotlin.fir.serialization.serializeSingleFirFile
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.getSerializedData
import org.jetbrains.kotlin.ir.backend.js.incrementalDataProvider
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerDesc
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.JsManglerIr
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.library.unresolvedDependencies
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.directives.CodegenTestDirectives
import org.jetbrains.kotlin.test.model.BackendKinds
import org.jetbrains.kotlin.test.model.Frontend2BackendConverter
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.compilerConfigurationProvider
import org.jetbrains.kotlin.test.services.libraryProvider
import org.jetbrains.kotlin.utils.metadataVersion
class Fir2IrWasmResultsConverter(
testServices: TestServices
) : Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>(
testServices,
FrontendKinds.FIR,
BackendKinds.IrBackend
) {
override fun transform(module: TestModule, inputArtifact: FirOutputArtifact): IrBackendInput? =
try {
transformInternal(module, inputArtifact)
} catch (e: Throwable) {
if (CodegenTestDirectives.IGNORE_FIR2IR_EXCEPTIONS_IF_FIR_CONTAINS_ERRORS in module.directives && inputArtifact.hasErrors) {
null
} else {
throw e
}
}
private fun transformInternal(
module: TestModule,
inputArtifact: FirOutputArtifact
): IrBackendInput {
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
lateinit var mainIrPart: IrModuleFragment
val dependentIrParts = mutableListOf<IrModuleFragment>()
val sourceFiles = mutableListOf<KtSourceFile>()
val firFilesAndComponentsBySourceFile = mutableMapOf<KtSourceFile, Pair<FirFile, Fir2IrComponents>>()
lateinit var mainPluginContext: IrPluginContext
var irBuiltIns: IrBuiltInsOverFir? = null
val commonMemberStorage = Fir2IrCommonMemberStorage(IdSignatureDescriptor(JsManglerDesc), FirJsKotlinMangler())
val irMangler = JsManglerIr
for ((index, part) in inputArtifact.partsForDependsOnModules.withIndex()) {
val (irModuleFragment, components, pluginContext) =
part.firAnalyzerFacade.convertToWasmIr(
part.firFiles.values,
fir2IrExtensions = Fir2IrExtensions.Default,
module,
configuration,
testServices,
commonMemberStorage,
irBuiltIns,
irMangler,
generateSignatures = true,
)
irBuiltIns = components.irBuiltIns
mainPluginContext = pluginContext
if (index < inputArtifact.partsForDependsOnModules.size - 1) {
dependentIrParts.add(irModuleFragment)
} else {
mainIrPart = irModuleFragment
}
sourceFiles.addAll(part.firFiles.mapNotNull { it.value.sourceFile })
for (firFile in part.firFiles.values) {
firFilesAndComponentsBySourceFile[firFile.sourceFile!!] = firFile to components
}
}
val metadataVersion = configuration.metadataVersion(module.languageVersionSettings.languageVersion)
var actualizedExpectDeclarations: Set<FirDeclaration>? = null
return IrBackendInput.WasmBackendInput(
mainIrPart,
dependentIrParts,
mainPluginContext,
sourceFiles,
configuration.incrementalDataProvider?.getSerializedData(sourceFiles) ?: emptyList(),
expectDescriptorToSymbol = mutableMapOf(),
diagnosticReporter = DiagnosticReporterFactory.createReporter(),
hasErrors = inputArtifact.hasErrors,
descriptorMangler = commonMemberStorage.symbolTable.signaturer.mangler,
irMangler = irMangler,
firMangler = commonMemberStorage.firSignatureComposer.mangler,
) { file, irActualizedResult ->
val (firFile, components) = firFilesAndComponentsBySourceFile[file]
?: error("cannot find FIR file by source file ${file.name} (${file.path})")
if (actualizedExpectDeclarations == null && irActualizedResult != null) {
actualizedExpectDeclarations = irActualizedResult.extractFirDeclarations()
}
serializeSingleFirFile(
firFile,
components.session,
components.scopeSession,
actualizedExpectDeclarations,
FirKLibSerializerExtension(
components.session, metadataVersion,
ConstValueProviderImpl(components),
allowErrorTypes = false, exportKDoc = false,
additionalAnnotationsProvider = null,
),
configuration.languageVersionSettings,
)
}
}
}
fun AbstractFirAnalyzerFacade.convertToWasmIr(
firFiles: Collection<FirFile>,
fir2IrExtensions: Fir2IrExtensions,
module: TestModule,
configuration: CompilerConfiguration,
testServices: TestServices,
commonMemberStorage: Fir2IrCommonMemberStorage,
irBuiltIns: IrBuiltInsOverFir?,
irMangler: KotlinMangler.IrMangler,
generateSignatures: Boolean
): Fir2IrResult {
this as FirAnalyzerFacade
// TODO: consider avoiding repeated libraries resolution
val libraries = resolveWasmLibraries(module, testServices, configuration)
val (dependencies, builtIns) = loadResolvedLibraries(libraries, configuration.languageVersionSettings, testServices)
val fir2IrConfiguration = Fir2IrConfiguration(
languageVersionSettings = configuration.languageVersionSettings,
linkViaSignatures = generateSignatures,
evaluatedConstTracker = configuration
.putIfAbsent(CommonConfigurationKeys.EVALUATED_CONST_TRACKER, EvaluatedConstTracker.create()),
inlineConstTracker = null,
)
return Fir2IrConverter.createModuleFragmentWithSignaturesIfNeeded(
session, scopeSession, firFiles.toList(),
fir2IrExtensions,
fir2IrConfiguration,
irMangler, IrFactoryImpl,
Fir2IrVisibilityConverter.Default,
Fir2IrJvmSpecialAnnotationSymbolProvider(), // TODO: replace with appropriate (probably empty) implementation
irGeneratorExtensions,
kotlinBuiltIns = builtIns ?: DefaultBuiltIns.Instance, // TODO: consider passing externally,
commonMemberStorage = commonMemberStorage,
initializedIrBuiltIns = irBuiltIns
).also {
(it.irModuleFragment.descriptor as? FirModuleDescriptor)?.let { it.allDependencyModules = dependencies }
}
}
private fun loadResolvedLibraries(
resolvedLibraries: List<KotlinResolvedLibrary>,
languageVersionSettings: LanguageVersionSettings,
testServices: TestServices
): Pair<List<ModuleDescriptor>, KotlinBuiltIns?> {
var builtInsModule: KotlinBuiltIns? = null
val dependencies = mutableListOf<ModuleDescriptorImpl>()
return resolvedLibraries.map { resolvedLibrary ->
// resolvedLibrary.library.libraryName in fact resolves to (modified) file path, which is confising and maybe should be refactored
testServices.libraryProvider.getOrCreateStdlibByPath(resolvedLibrary.library.libraryName) {
// TODO: check safety of the approach of creating a separate storage manager per library
val storageManager = LockBasedStorageManager("ModulesStructure")
val moduleDescriptor = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
resolvedLibrary.library,
languageVersionSettings,
storageManager,
builtInsModule,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
dependencies += moduleDescriptor
moduleDescriptor.setDependencies(ArrayList(dependencies))
Pair(moduleDescriptor, resolvedLibrary.library)
}.also {
val isBuiltIns = resolvedLibrary.library.unresolvedDependencies.isEmpty()
if (isBuiltIns) builtInsModule = it.builtIns
}
} to builtInsModule
}
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.isJs
import org.jetbrains.kotlin.platform.isWasm
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.platform.konan.isNative
import org.jetbrains.kotlin.psi.KtFile
@@ -55,6 +56,7 @@ import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.runners.lightTreeSyntaxDiagnosticsReporterHolder
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.JsEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfigurator
import java.nio.file.Paths
open class FirFrontendFacade(
@@ -240,6 +242,20 @@ open class FirFrontendFacade(
registerExtraComponents = ::registerExtraComponents,
)
}
module.targetPlatform.isWasm() -> {
projectEnvironment = null
TestFirWasmSessionFactory.createLibrarySession(
moduleName,
sessionProvider,
moduleDataProvider,
module,
testServices,
configuration,
extensionRegistrars,
languageVersionSettings,
registerExtraComponents = ::registerExtraComponents,
)
}
else -> error("Unsupported")
}
return projectEnvironment
@@ -380,6 +396,17 @@ open class FirFrontendFacade(
init = sessionConfigurator
)
}
targetPlatform.isWasm() -> {
TestFirWasmSessionFactory.createModuleBasedSession(
moduleData,
sessionProvider,
extensionRegistrars,
languageVersionSettings,
null,
registerExtraComponents = ::registerExtraComponents,
sessionConfigurator,
)
}
else -> error("Unsupported")
}
}
@@ -413,6 +440,13 @@ open class FirFrontendFacade(
dependencies(transitiveLibraries.map { it.toPath().toAbsolutePath() })
friendDependencies(friendLibraries.map { it.toPath().toAbsolutePath() })
}
targetPlatform.isWasm() -> {
val runtimeKlibsPaths = WasmEnvironmentConfigurator.getRuntimePathsForModule()
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")
}
}
@@ -0,0 +1,88 @@
/*
* Copyright 2010-2021 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.frontend.fir
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.deserialization.ModuleDataProvider
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
import org.jetbrains.kotlin.fir.session.FirSessionConfigurator
import org.jetbrains.kotlin.fir.session.FirWasmSessionFactory
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.resolverLogger
import org.jetbrains.kotlin.library.metadata.resolver.KotlinResolvedLibrary
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.test.model.DependencyRelation
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfigurator
import java.io.File
object TestFirWasmSessionFactory {
fun createLibrarySession(
mainModuleName: Name,
sessionProvider: FirProjectSessionProvider,
moduleDataProvider: ModuleDataProvider,
module: TestModule,
testServices: TestServices,
configuration: CompilerConfiguration,
extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings,
registerExtraComponents: ((FirSession) -> Unit),
): FirSession {
val resolvedLibraries = resolveLibraries(configuration, getAllWasmDependenciesPaths(module, testServices))
return FirWasmSessionFactory.createLibrarySession(
mainModuleName,
resolvedLibraries.map { it.library },
sessionProvider,
moduleDataProvider,
extensionRegistrars,
languageVersionSettings,
registerExtraComponents,
)
}
fun createModuleBasedSession(
mainModuleData: FirModuleData, sessionProvider: FirProjectSessionProvider, extensionRegistrars: List<FirExtensionRegistrar>,
languageVersionSettings: LanguageVersionSettings, lookupTracker: LookupTracker?,
registerExtraComponents: ((FirSession) -> Unit),
sessionConfigurator: FirSessionConfigurator.() -> Unit,
): FirSession =
FirWasmSessionFactory.createModuleBasedSession(
mainModuleData,
sessionProvider,
extensionRegistrars,
languageVersionSettings,
lookupTracker,
icData = null,
registerExtraComponents,
sessionConfigurator
)
}
fun resolveWasmLibraries(
module: TestModule,
testServices: TestServices,
configuration: CompilerConfiguration
): List<KotlinResolvedLibrary> {
return resolveLibraries(configuration, getAllWasmDependenciesPaths(module, testServices))
}
fun getAllWasmDependenciesPaths(module: TestModule, testServices: TestServices): List<String> {
val (runtimeKlibsPaths, transitiveLibraries, friendLibraries) = getWasmDependencies(module, testServices)
return runtimeKlibsPaths + transitiveLibraries.map { it.path } + friendLibraries.map { it.path }
}
fun getWasmDependencies(module: TestModule, testServices: TestServices): Triple<List<String>, List<File>, List<File>> {
val runtimeKlibsPaths = WasmEnvironmentConfigurator.getRuntimePathsForModule()
val transitiveLibraries = WasmEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.RegularDependency)
val friendLibraries = WasmEnvironmentConfigurator.getKlibDependencies(module, testServices, DependencyRelation.FriendDependency)
return Triple(runtimeKlibsPaths, transitiveLibraries, friendLibraries)
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.test.model
import org.jetbrains.kotlin.KtSourceFile
import org.jetbrains.kotlin.backend.wasm.WasmCompilerResult
import org.jetbrains.kotlin.codegen.ClassFileFactory
import org.jetbrains.kotlin.fileClasses.JvmFileClassInfo
import org.jetbrains.kotlin.ir.backend.js.CompilerResult
@@ -49,6 +50,14 @@ object BinaryArtifacts {
get() = ArtifactKinds.Native
}
class Wasm(
val compilerResult: WasmCompilerResult,
val compilerResultWithDCE: WasmCompilerResult,
) : ResultingArtifact.Binary<Wasm>() {
override val kind: BinaryKind<Wasm>
get() = ArtifactKinds.Wasm
}
class KLib(val outputFile: File) : ResultingArtifact.Binary<KLib>() {
override val kind: BinaryKind<KLib>
get() = ArtifactKinds.KLib
@@ -50,6 +50,7 @@ object ArtifactKinds {
object Jvm : BinaryKind<BinaryArtifacts.Jvm>("JVM")
object Js : BinaryKind<BinaryArtifacts.Js>("JS")
object Native : BinaryKind<BinaryArtifacts.Native>("Native")
object Wasm : BinaryKind<BinaryArtifacts.Wasm>("Wasm")
object KLib : BinaryKind<BinaryArtifacts.KLib>("KLib")
fun fromString(string: String): BinaryKind<*>? {
@@ -57,6 +58,7 @@ object ArtifactKinds {
"Jvm" -> Jvm
"Js" -> Js
"Native" -> Native
"Wasm" -> Wasm
"KLib" -> KLib
else -> null
}
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.test.model.DependencyRelation
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.dependencyProvider
import org.jetbrains.kotlin.test.services.jsLibraryProvider
import org.jetbrains.kotlin.test.services.libraryProvider
import java.io.File
fun getKlibDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<File> {
@@ -39,5 +39,5 @@ fun getKlibDependencies(module: TestModule, testServices: TestServices, kind: De
fun getDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<ModuleDescriptor> {
return getKlibDependencies(module, testServices, kind)
.map { testServices.jsLibraryProvider.getDescriptorByPath(it.absolutePath) }
.map { testServices.libraryProvider.getDescriptorByPath(it.absolutePath) }
}
@@ -11,16 +11,19 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.SourceMapSourceEmbedding
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives.INFER_MAIN_MODULE
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives.EXPECT_ACTUAL_LINKER
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives.NO_INLINE
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives.PROPERTY_LAZY_INITIALIZATION
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives.SOURCE_MAP_EMBED_SOURCES
import org.jetbrains.kotlin.test.directives.WasmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.model.DirectivesContainer
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.frontend.classic.moduleDescriptorProvider
import org.jetbrains.kotlin.test.model.ArtifactKinds
import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.model.DependencyRelation
@@ -30,7 +33,98 @@ import java.io.File
class WasmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
override val directiveContainers: List<DirectivesContainer>
get() = listOf(JsEnvironmentConfigurationDirectives)
get() = listOf(WasmEnvironmentConfigurationDirectives)
companion object {
private const val OUTPUT_KLIB_DIR_NAME = "outputKlibDir"
fun getRuntimePathsForModule(): List<String> {
return listOf(System.getProperty("kotlin.wasm.stdlib.path")!!, System.getProperty("kotlin.wasm.kotlin.test.path")!!)
}
fun getKlibDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<File> {
val visited = mutableSetOf<TestModule>()
fun getRecursive(module: TestModule, relation: DependencyRelation) {
val dependencies = if (relation == DependencyRelation.FriendDependency) {
module.friendDependencies
} else {
module.regularDependencies
}
dependencies
.filter { it.kind != DependencyKind.Source }
.map { testServices.dependencyProvider.getTestModule(it.moduleName) }.forEach {
if (it !in visited) {
visited += it
getRecursive(it, relation)
}
}
}
getRecursive(module, kind)
return visited.map { testServices.dependencyProvider.getArtifact(it, ArtifactKinds.KLib).outputFile }
}
fun getDependencies(module: TestModule, testServices: TestServices, kind: DependencyRelation): List<ModuleDescriptor> {
return getKlibDependencies(module, testServices, kind)
.map { testServices.libraryProvider.getDescriptorByPath(it.absolutePath) }
}
fun getWasmKlibArtifactPath(testServices: TestServices, moduleName: String): String {
return getWasmKlibOutputDir(testServices).absolutePath + File.separator + JsEnvironmentConfigurator.getJsArtifactSimpleName(
testServices,
moduleName
)
}
fun getWasmKlibOutputDir(testServices: TestServices): File {
return testServices.temporaryDirectoryManager.getOrCreateTempDirectory(OUTPUT_KLIB_DIR_NAME)
}
fun getAllRecursiveDependenciesFor(module: TestModule, testServices: TestServices): Set<ModuleDescriptorImpl> {
val visited = mutableSetOf<ModuleDescriptorImpl>()
fun getRecursive(descriptor: ModuleDescriptor) {
descriptor.allDependencyModules.forEach {
if (it is ModuleDescriptorImpl && it !in visited) {
visited += it
getRecursive(it)
}
}
}
getRecursive(testServices.moduleDescriptorProvider.getModuleDescriptor(module))
return visited
}
fun getAllRecursiveLibrariesFor(module: TestModule, testServices: TestServices): Map<KotlinLibrary, ModuleDescriptorImpl> {
val dependencies = getAllRecursiveDependenciesFor(module, testServices)
return dependencies.associateBy { testServices.libraryProvider.getCompiledLibraryByDescriptor(it) }
}
fun getAllDependenciesMappingFor(module: TestModule, testServices: TestServices): Map<KotlinLibrary, List<KotlinLibrary>> {
val allRecursiveLibraries: Map<KotlinLibrary, ModuleDescriptor> =
getAllRecursiveLibrariesFor(module, testServices)
val m2l = allRecursiveLibraries.map { it.value to it.key }.toMap()
return allRecursiveLibraries.keys.associateWith { m ->
val descriptor = allRecursiveLibraries[m] ?: error("No descriptor found for library ${m.libraryName}")
descriptor.allDependencyModules.filter { it != descriptor }.map { m2l.getValue(it) }
}
}
fun getMainModule(testServices: TestServices): TestModule {
val modules = testServices.moduleStructure.modules
val inferMainModule = INFER_MAIN_MODULE in testServices.moduleStructure.allDirectives
return when {
inferMainModule -> modules.last()
else -> modules.singleOrNull { it.name == ModuleStructureExtractor.DEFAULT_MODULE_NAME } ?: modules.last()
}
}
fun isMainModule(module: TestModule, testServices: TestServices): Boolean {
return module == getMainModule(testServices)
}
}
override fun provideAdditionalAnalysisFlags(
directives: RegisteredDirectives,
@@ -48,11 +142,11 @@ class WasmEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfi
override fun configureCompilerConfiguration(configuration: CompilerConfiguration, module: TestModule) {
val registeredDirectives = module.directives
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.ES)
val noInline = registeredDirectives.contains(NO_INLINE)
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, noInline)
configuration.put(CommonConfigurationKeys.MODULE_NAME, module.name)
configuration.put(JSConfigurationKeys.WASM_ENABLE_ASSERTS, true)
configuration.put(JSConfigurationKeys.WASM_ENABLE_ARRAY_RANGE_CHECKS, true)
val sourceDirs = module.files.map { it.originalFile.parent }.distinct()
configuration.put(JSConfigurationKeys.SOURCE_MAP_SOURCE_ROOTS, sourceDirs)
configuration.put(JSConfigurationKeys.SOURCE_MAP, true)
+6 -11
View File
@@ -133,23 +133,18 @@ val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateWa
dependsOn(":compiler:generateTestData")
}
projectTest(parallel = true) {
workingDir = rootDir
exclude("**/diagnostics/*.class")
setupV8()
setupSpiderMonkey()
setupWasmStdlib()
setupGradlePropertiesForwarding()
systemProperty("kotlin.wasm.test.root.out.dir", "$buildDir/")
}
projectTest(
taskName = "diagnosticsTest",
taskName = "test",
parallel = true,
jUnitMode = JUnitMode.JUnit5
) {
workingDir = rootDir
include("**/diagnostics/*.class")
include("**/FirWasm*.class")
include("**/K1Wasm*.class")
include("**/Wasm*.class")
setupV8()
setupSpiderMonkey()
useJUnitPlatform()
setupWasmStdlib()
setupGradlePropertiesForwarding()
@@ -1,60 +1,29 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.generators.tests
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
import org.jetbrains.kotlin.generators.impl.generateTestGroupSuite
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.wasm.test.*
import org.jetbrains.kotlin.wasm.test.diagnostics.AbstractDiagnosticsWasmTest
fun main(args: Array<String>) {
System.setProperty("java.awt.headless", "true")
// Common configuration shared between K1 and K2 tests:
val jvmOnlyBoxTests = listOf(
"compileKotlinAgainstKotlin",
)
generateTestGroupSuite(args) {
val jsTranslatorTestPattern = "^([^_](.+))\\.kt$"
testGroup("wasm/wasm.tests/tests-gen", "js/js.translator/testData", testRunnerMethodName = "runTest0") {
testClass<AbstractJsTranslatorWasmTest> {
model("box/main", pattern = jsTranslatorTestPattern, targetBackend = TargetBackend.WASM)
model("box/native/", pattern = jsTranslatorTestPattern, targetBackend = TargetBackend.WASM)
model("box/esModules/", pattern = jsTranslatorTestPattern, targetBackend = TargetBackend.WASM,
excludeDirs = listOf(
// JsExport is not supported for classes
"jsExport", "native", "export",
// Multimodal infra is not supported. Also, we don't use ES modules for cross-module refs in Wasm
"crossModuleRef", "crossModuleRefPerFile", "crossModuleRefPerModule"
)
)
model("box/jsQualifier/", pattern = jsTranslatorTestPattern, targetBackend = TargetBackend.WASM)
model("box/reflection/", pattern = "^(findAssociatedObject(InSeparatedFile)?)\\.kt$", targetBackend = TargetBackend.WASM)
}
testClass<AbstractJsTranslatorUnitWasmTest> {
model("box/kotlin.test/", pattern = jsTranslatorTestPattern, targetBackend = TargetBackend.WASM)
}
}
testGroup("wasm/wasm.tests/tests-gen", "compiler/testData", testRunnerMethodName = "runTest0") {
testClass<AbstractIrCodegenBoxWasmTest> {
model("codegen/box", targetBackend = TargetBackend.WASM, pattern = jsTranslatorTestPattern, excludeDirs = jvmOnlyBoxTests)
}
testClass<AbstractIrCodegenBoxInlineWasmTest> {
model("codegen/boxInline", targetBackend = TargetBackend.WASM)
}
testClass<AbstractIrCodegenWasmJsInteropWasmTest> {
model("codegen/boxWasmJsInterop", targetBackend = TargetBackend.WASM)
}
}
}
val jsTranslatorTestPattern = "^([^_](.+))\\.kt$"
val jsTranslatorReflectionPattern = "^(findAssociatedObject(InSeparatedFile)?)\\.kt$"
val jsTranslatorEsModulesExcludedDirs = listOf(
// JsExport is not supported for classes
"jsExport", "native", "export",
// Multimodal infra is not supported. Also, we don't use ES modules for cross-module refs in Wasm
"crossModuleRef", "crossModuleRefPerFile", "crossModuleRefPerModule"
)
generateTestGroupSuiteWithJUnit5(args) {
testGroup("wasm/wasm.tests/tests-gen", "compiler/testData") {
@@ -62,5 +31,55 @@ fun main(args: Array<String>) {
model("diagnostics/wasmTests")
}
}
testGroup("wasm/wasm.tests/tests-gen", "js/js.translator/testData", testRunnerMethodName = "runTest0") {
testClass<AbstractFirWasmJsTranslatorTest> {
model("box/main", pattern = jsTranslatorTestPattern)
model("box/native/", pattern = jsTranslatorTestPattern)
model("box/esModules/", pattern = jsTranslatorTestPattern, excludeDirs = jsTranslatorEsModulesExcludedDirs)
model("box/jsQualifier/", pattern = jsTranslatorTestPattern)
model("box/reflection/", pattern = jsTranslatorReflectionPattern)
model("box/kotlin.test/", pattern = jsTranslatorTestPattern)
}
}
testGroup("wasm/wasm.tests/tests-gen", "compiler/testData", testRunnerMethodName = "runTest0") {
testClass<AbstractFirWasmCodegenBoxTest> {
model("codegen/box", pattern = jsTranslatorTestPattern, excludeDirs = jvmOnlyBoxTests)
}
testClass<AbstractFirWasmCodegenBoxInlineTest> {
model("codegen/boxInline")
}
testClass<AbstractFirWasmCodegenWasmJsInteropTest> {
model("codegen/boxWasmJsInterop")
}
}
testGroup("wasm/wasm.tests/tests-gen", "js/js.translator/testData", testRunnerMethodName = "runTest0") {
testClass<AbstractK1WasmJsTranslatorTest> {
model("box/main", pattern = jsTranslatorTestPattern)
model("box/native/", pattern = jsTranslatorTestPattern)
model("box/esModules/", pattern = jsTranslatorTestPattern, excludeDirs = jsTranslatorEsModulesExcludedDirs)
model("box/jsQualifier/", pattern = jsTranslatorTestPattern)
model("box/reflection/", pattern = jsTranslatorReflectionPattern)
model("box/kotlin.test/", pattern = jsTranslatorTestPattern)
}
}
testGroup("wasm/wasm.tests/tests-gen", "compiler/testData", testRunnerMethodName = "runTest0") {
testClass<AbstractK1WasmCodegenBoxTest> {
model("codegen/box", pattern = jsTranslatorTestPattern, excludeDirs = jvmOnlyBoxTests)
}
testClass<AbstractK1WasmCodegenBoxInlineTest> {
model("codegen/boxInline")
}
testClass<AbstractK1WasmCodegenWasmJsInteropTest> {
model("codegen/boxWasmJsInterop")
}
}
}
}
@@ -0,0 +1,92 @@
/*
* 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.wasm.test
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.FirParser
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.builders.*
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
import org.jetbrains.kotlin.test.frontend.fir.*
import org.jetbrains.kotlin.test.frontend.fir.handlers.*
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.codegen.commonFirHandlersForCodegenTest
import org.jetbrains.kotlin.wasm.test.converters.FirWasmKlibBackendFacade
import org.jetbrains.kotlin.wasm.test.converters.WasmBackendFacade
open class AbstractFirWasmTest(
pathToTestDir: String,
testGroupOutputDirPrefix: String,
) : AbstractWasmBlackBoxCodegenTestBase<FirOutputArtifact, IrBackendInput, BinaryArtifacts.KLib>(
FrontendKinds.FIR, TargetBackend.WASM, pathToTestDir, testGroupOutputDirPrefix
) {
override val frontendFacade: Constructor<FrontendFacade<FirOutputArtifact>>
get() = ::FirFrontendFacade
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<FirOutputArtifact, IrBackendInput>>
get() = ::Fir2IrWasmResultsConverter
override val backendFacade: Constructor<BackendFacade<IrBackendInput, BinaryArtifacts.KLib>>
get() = ::FirWasmKlibBackendFacade
override val afterBackendFacade: Constructor<AbstractTestFacade<BinaryArtifacts.KLib, BinaryArtifacts.Wasm>>
get() = ::WasmBackendFacade
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
with(builder) {
defaultDirectives {
+LanguageSettingsDirectives.ALLOW_KOTLIN_PACKAGE
DiagnosticsDirectives.DIAGNOSTICS with listOf("-infos")
FirDiagnosticsDirectives.FIR_PARSER with FirParser.Psi
}
firHandlersStep {
useHandlers(
::FirDumpHandler,
::FirCfgDumpHandler,
::FirCfgConsistencyHandler,
::FirResolvedTypesVerifier,
)
}
}
}
}
open class AbstractFirWasmCodegenBoxTest : AbstractFirWasmTest(
pathToTestDir = "compiler/testData/codegen/box/",
testGroupOutputDirPrefix = "codegen/firBox/"
) {
override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder)
builder.configureFirHandlersStep {
commonFirHandlersForCodegenTest()
}
builder.useAfterAnalysisCheckers(
::FirMetaInfoDiffSuppressor
)
}
}
open class AbstractFirWasmCodegenBoxInlineTest : AbstractFirWasmTest(
"compiler/testData/codegen/boxInline/",
"codegen/firBoxInline/"
)
open class AbstractFirWasmCodegenWasmJsInteropTest : AbstractFirWasmTest(
"compiler/testData/codegen/wasmJsInterop",
"codegen/firWasmJsInterop"
)
open class AbstractFirWasmJsTranslatorTest : AbstractFirWasmTest(
"js/js.translator/testData/box/",
"js.translator/firBox"
)
@@ -0,0 +1,55 @@
/*
* 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.wasm.test
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontend2IrConverter
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.wasm.test.converters.FirWasmKlibBackendFacade
import org.jetbrains.kotlin.wasm.test.converters.WasmBackendFacade
abstract class AbstractK1WasmTest(
pathToTestDir: String,
testGroupOutputDirPrefix: String,
) : AbstractWasmBlackBoxCodegenTestBase<ClassicFrontendOutputArtifact, IrBackendInput, BinaryArtifacts.KLib>(
FrontendKinds.ClassicFrontend, TargetBackend.WASM, pathToTestDir, testGroupOutputDirPrefix
) {
override val frontendFacade: Constructor<FrontendFacade<ClassicFrontendOutputArtifact>>
get() = ::ClassicFrontendFacade
override val frontendToBackendConverter: Constructor<Frontend2BackendConverter<ClassicFrontendOutputArtifact, IrBackendInput>>
get() = ::ClassicFrontend2IrConverter
override val backendFacade: Constructor<BackendFacade<IrBackendInput, BinaryArtifacts.KLib>>
get() = ::FirWasmKlibBackendFacade
override val afterBackendFacade: Constructor<AbstractTestFacade<BinaryArtifacts.KLib, BinaryArtifacts.Wasm>>
get() = ::WasmBackendFacade
}
open class AbstractK1WasmCodegenBoxTest : AbstractK1WasmTest(
"compiler/testData/codegen/box/",
"codegen/k1Box/"
)
open class AbstractK1WasmCodegenBoxInlineTest : AbstractK1WasmTest(
"compiler/testData/codegen/boxInline/",
"codegen/k1BoxInline/"
)
open class AbstractK1WasmCodegenWasmJsInteropTest : AbstractK1WasmTest(
"compiler/testData/codegen/wasmJsInterop",
"codegen/k1WasmJsInteropBox"
)
open class AbstractK1WasmJsTranslatorTest : AbstractK1WasmTest(
"js/js.translator/testData/box/",
"js.translator/k1Box"
)
@@ -0,0 +1,112 @@
/*
* 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.wasm.test
import org.jetbrains.kotlin.platform.wasm.WasmPlatforms
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.backend.BlackBoxCodegenSuppressor
import org.jetbrains.kotlin.test.backend.handlers.KlibInterpreterDumpHandler
import org.jetbrains.kotlin.test.backend.handlers.WasmIrInterpreterDumpHandler
import org.jetbrains.kotlin.test.builders.*
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.DIAGNOSTICS
import org.jetbrains.kotlin.test.directives.WasmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticsHandler
import org.jetbrains.kotlin.test.model.*
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
import org.jetbrains.kotlin.test.runners.codegen.commonClassicFrontendHandlersForCodegenTest
import org.jetbrains.kotlin.test.services.LibraryProvider
import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfigurator
import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider
import org.jetbrains.kotlin.wasm.test.handlers.WasmBoxRunner
abstract class AbstractWasmBlackBoxCodegenTestBase<R : ResultingArtifact.FrontendOutput<R>, I : ResultingArtifact.BackendInput<I>, A : ResultingArtifact.Binary<A>>(
private val targetFrontend: FrontendKind<R>,
targetBackend: TargetBackend,
private val pathToTestDir: String,
private val testGroupOutputDirPrefix: String,
) : AbstractKotlinCompilerWithTargetBackendTest(targetBackend) {
abstract val frontendFacade: Constructor<FrontendFacade<R>>
abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<R, I>>
abstract val backendFacade: Constructor<BackendFacade<I, A>>
abstract val afterBackendFacade: Constructor<AbstractTestFacade<A, BinaryArtifacts.Wasm>>
override fun TestConfigurationBuilder.configuration() {
globalDefaults {
frontend = targetFrontend
targetPlatform = WasmPlatforms.Default
dependencyKind = DependencyKind.Binary
}
val pathToRootOutputDir = System.getProperty("kotlin.wasm.test.root.out.dir") ?: error("'kotlin.wasm.test.root.out.dir' is not set")
defaultDirectives {
+DiagnosticsDirectives.REPORT_ONLY_EXPLICITLY_DEFINED_DEBUG_INFO
WasmEnvironmentConfigurationDirectives.PATH_TO_ROOT_OUTPUT_DIR with pathToRootOutputDir
WasmEnvironmentConfigurationDirectives.PATH_TO_TEST_DIR with pathToTestDir
WasmEnvironmentConfigurationDirectives.TEST_GROUP_OUTPUT_DIR_PREFIX with testGroupOutputDirPrefix
}
forTestsNotMatching("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/*") {
defaultDirectives {
DIAGNOSTICS with "-warnings"
}
}
forTestsNotMatching("compiler/testData/codegen/boxError/*") {
enableMetaInfoHandler()
}
useConfigurators(
::WasmEnvironmentConfigurator,
)
useAdditionalSourceProviders(
::WasmAdditionalSourceProvider,
::CoroutineHelpersSourceFilesProvider,
)
useAdditionalService(::LibraryProvider)
useAfterAnalysisCheckers(
::WasmFailingTestSuppressor,
::BlackBoxCodegenSuppressor,
)
facadeStep(frontendFacade)
classicFrontendHandlersStep {
commonClassicFrontendHandlersForCodegenTest()
useHandlers(::ClassicDiagnosticsHandler)
}
firHandlersStep {
useHandlers(::FirDiagnosticsHandler)
}
facadeStep(frontendToBackendConverter)
irHandlersStep()
facadeStep(backendFacade)
klibArtifactsHandlersStep()
facadeStep(afterBackendFacade)
forTestsMatching("compiler/testData/codegen/box/involvesIrInterpreter/*") {
enableMetaInfoHandler()
configureKlibArtifactsHandlersStep {
useHandlers(::KlibInterpreterDumpHandler)
}
configureWasmArtifactsHandlersStep {
useHandlers(::WasmIrInterpreterDumpHandler)
}
}
wasmArtifactsHandlersStep {
useHandlers(::WasmBoxRunner)
}
}
}
@@ -1,416 +0,0 @@
/*
* Copyright 2010-2021 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.wasm.test
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.ObsoleteTestInfrastructure
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
import org.jetbrains.kotlin.backend.wasm.*
import org.jetbrains.kotlin.backend.wasm.dce.eliminateDeadDeclarations
import org.jetbrains.kotlin.checkers.parseLanguageVersionSettings
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.cli.js.klib.TopDownAnalyzerFacadeForWasm
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.ir.backend.js.dce.dumpDeclarationIrSizesIfNeed
import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.wasm.test.tools.WasmVM
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.serialization.js.ModuleKind
import org.jetbrains.kotlin.test.*
import org.jetbrains.kotlin.test.util.KtTestUtil
import java.io.Closeable
import java.io.File
abstract class BasicWasmBoxTest(
private val pathToTestDir: String,
testGroupOutputDirPrefix: String,
private val startUnitTests: Boolean = false
) : KotlinTestWithEnvironment() {
private val pathToRootOutputDir: String = System.getProperty("kotlin.wasm.test.root.out.dir") ?: error("'kotlin.wasm.test.root.out.dir' is not set")
private val testGroupOutputDirForCompilation = File(pathToRootOutputDir + "out/" + testGroupOutputDirPrefix)
private val COMMON_FILES_NAME = "_common"
private val COMMON_FILES_DIR = "_commonFiles"
private val extraLanguageFeatures = mapOf(
LanguageFeature.JsAllowImplementingFunctionInterface to LanguageFeature.State.ENABLED,
)
fun doTest(filePath: String) = doTestWithTransformer(filePath) { it }
@OptIn(ObsoleteTestInfrastructure::class)
fun doTestWithTransformer(filePath: String, transformer: java.util.function.Function<String, String>) {
val file = File(filePath)
val outputDirBase = File(getOutputDir(file), getTestName(true))
val fileContent = transformer.apply(KtTestUtil.doLoadFile(file))
TestFileFactoryImpl().use { testFactory ->
val inputFiles: MutableList<TestFile> = TestFiles.createTestFiles(file.name, fileContent, testFactory, true)
val testPackage = testFactory.testPackage
val languageVersionSettings = inputFiles.firstNotNullOfOrNull { it.languageVersionSettings }
val kotlinFiles = mutableListOf<String>()
val jsFiles = mutableListOf<String>()
val mjsFiles = mutableListOf<String>()
var entryMjs: String? = "test.mjs"
inputFiles.forEach {
val name = it.fileName
when {
name.endsWith(".kt") ->
kotlinFiles += name
name.endsWith(".js") ->
jsFiles += name
name.endsWith(".mjs") -> {
mjsFiles += name
val fileName = File(name).name
if (fileName == "entry.mjs") {
entryMjs = fileName
}
}
}
}
val additionalJsFile = filePath.removeSuffix(".kt") + ".js"
if (File(additionalJsFile).exists()) {
jsFiles += additionalJsFile
}
val additionalMjsFile = filePath.removeSuffix(".kt") + ".mjs"
if (File(additionalMjsFile).exists()) {
mjsFiles += additionalMjsFile
}
val localCommonFile = file.parent + "/" + COMMON_FILES_NAME + "." + KotlinFileType.EXTENSION
val localCommonFiles = if (File(localCommonFile).exists()) listOf(localCommonFile) else emptyList()
val globalCommonFilesDir = File(File(pathToTestDir).parent, COMMON_FILES_DIR)
val globalCommonFiles = globalCommonFilesDir.listFiles().orEmpty().map { it.absolutePath }
val allSourceFiles = kotlinFiles + localCommonFiles + globalCommonFiles
val psiFiles = createPsiFiles(allSourceFiles.map { File(it).canonicalPath }.sorted())
val config = createConfig(languageVersionSettings)
val filesToCompile = psiFiles.map { TranslationUnit.SourceFile(it).file }
val debugMode = DebugMode.fromSystemProperty("kotlin.wasm.debugMode")
val phaseConfig = if (debugMode >= DebugMode.SUPER_DEBUG) {
val dumpOutputDir = File(outputDirBase, "irdump")
println("\n ------ Dumping phases to file://${dumpOutputDir.absolutePath}")
PhaseConfig(
wasmPhases,
dumpToDirectory = dumpOutputDir.path,
toDumpStateAfter = wasmPhases.toPhaseMap().values.toSet(),
)
} else {
PhaseConfig(wasmPhases)
}
if (debugMode >= DebugMode.DEBUG) {
println(" ------ KT file://${file.absolutePath}")
}
val sourceModule = prepareAnalyzedSourceModule(
config.project,
filesToCompile,
config.configuration,
// TODO: Bypass the resolver fow wasm.
listOf(System.getProperty("kotlin.wasm.stdlib.path")!!, System.getProperty("kotlin.wasm.kotlin.test.path")!!),
emptyList(),
AnalyzerWithCompilerReport(config.configuration),
analyzerFacade = TopDownAnalyzerFacadeForWasm
)
val (allModules, backendContext) = compileToLoweredIr(
depsDescriptors = sourceModule,
phaseConfig = phaseConfig,
irFactory = IrFactoryImpl,
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, TEST_FUNCTION))),
propertyLazyInitialization = true,
)
val generateWat = debugMode >= DebugMode.DEBUG
val baseFileName = "index"
val compilerResult = compileWasm(
allModules = allModules,
backendContext = backendContext,
baseFileName = baseFileName,
emitNameSection = true,
allowIncompleteImplementations = false,
generateWat = generateWat,
)
eliminateDeadDeclarations(allModules, backendContext)
dumpDeclarationIrSizesIfNeed(System.getProperty("kotlin.wasm.dump.declaration.ir.size.to.file"), allModules)
val compilerResultWithDCE = compileWasm(
allModules = allModules,
backendContext = backendContext,
baseFileName = baseFileName,
emitNameSection = true,
allowIncompleteImplementations = true,
generateWat = generateWat,
)
val testJsQuiet = """
let actualResult;
try {
// Use "dynamic import" to catch exception happened during JS & Wasm modules initialization
let jsModule = await import('./index.mjs');
let wasmExports = jsModule.default;
${if (startUnitTests) "wasmExports.startUnitTests();" else ""}
actualResult = wasmExports.box();
} catch(e) {
console.log('Failed with exception!')
console.log('Message: ' + e.message)
console.log('Name: ' + e.name)
console.log('Stack:')
console.log(e.stack)
}
if (actualResult !== "OK")
throw `Wrong box result '${'$'}{actualResult}'; Expected "OK"`;
""".trimIndent()
val testJsVerbose = testJsQuiet + """
console.log('test passed');
""".trimIndent()
val testJs = if (debugMode >= DebugMode.DEBUG) testJsVerbose else testJsQuiet
fun printPathAndSize(mode: String, fileKind: String, path: String, name: String) {
val size = File("$path/$name").length()
println(" ------ $mode $fileKind file://$path/$name $size B")
}
fun checkExpectedOutputSize(testFileContent: String, testDir: File) {
val expectedSizes =
InTextDirectivesUtils.findListWithPrefixes(testFileContent, "// WASM_DCE_EXPECTED_OUTPUT_SIZE: ")
.map {
val i = it.indexOf(' ')
val extension = it.substring(0, i)
val size = it.substring(i + 1)
extension.trim().lowercase() to size.filter(Char::isDigit).toInt()
}
val filesByExtension = testDir.listFiles()?.groupBy { it.extension }.orEmpty()
val errors = expectedSizes.mapNotNull { (extension, expectedSize) ->
val totalSize = filesByExtension[extension].orEmpty().sumOf { it.length() }
val thresholdPercent = 1
val thresholdInBytes = expectedSize * thresholdPercent / 100
val expectedMinSize = expectedSize - thresholdInBytes
val expectedMaxSize = expectedSize + thresholdInBytes
val diff = totalSize - expectedSize
val message = "Total size of $extension files is $totalSize," +
" but expected $expectedSize$thresholdInBytes [$expectedMinSize .. $expectedMaxSize]." +
" Diff: $diff (${diff * 100 / expectedSize}%)"
if (debugMode >= DebugMode.DEBUG) {
println(" ------ $message")
}
if (totalSize !in expectedMinSize..expectedMaxSize) message else null
}
if (errors.isNotEmpty()) throw AssertionError(errors.joinToString("\n"))
}
fun writeToFilesAndRunTest(mode: String, res: WasmCompilerResult) {
val dir = File(outputDirBase, mode)
dir.mkdirs()
writeCompilationResult(res, dir, baseFileName)
File(dir, "test.mjs").writeText(testJs)
for (mjsPath: String in mjsFiles) {
val mjsFile = File(mjsPath)
File(dir, mjsFile.name).writeText(mjsFile.readText())
}
if (debugMode >= DebugMode.DEBUG) {
File(dir, "index.html").writeText(
"""
<!DOCTYPE html>
<html lang="en">
<body>
<span id="test">UNKNOWN</span>
<script type="module">
let test = document.getElementById("test")
try {
await import("./test.mjs");
test.style.backgroundColor = "#0f0";
test.textContent = "OK"
} catch(e) {
test.style.backgroundColor = "#f00";
test.textContent = "NOT OK"
throw e;
}
</script>
</body>
</html>
""".trimIndent()
)
val path = dir.absolutePath
println(" ------ $mode Wat file://$path/index.wat")
println(" ------ $mode Wasm file://$path/index.wasm")
println(" ------ $mode JS file://$path/index.uninstantiated.mjs")
println(" ------ $mode JS file://$path/index.mjs")
println(" ------ $mode Test file://$path/test.mjs")
val projectName = "kotlin"
println(" ------ $mode HTML http://0.0.0.0:63342/$projectName/${dir.path}/index.html")
for (mjsPath: String in mjsFiles) {
println(" ------ $mode External ESM file://$path/${File(mjsPath).name}")
}
}
val testFile = file.readText()
val failsIn = InTextDirectivesUtils.findListWithPrefixes(testFile, "// WASM_FAILS_IN: ")
val exceptions = listOf(WasmVM.V8, WasmVM.SpiderMonkey).mapNotNull map@{ vm ->
try {
if (debugMode >= DebugMode.DEBUG) {
println(" ------ Run in ${vm.name}" + if (vm.shortName in failsIn) " (expected to fail)" else "")
}
vm.run(
"./${entryMjs}",
jsFiles.map { File(it).absolutePath },
workingDirectory = dir
)
if (vm.shortName in failsIn) {
return@map AssertionError("The test expected to fail in ${vm.name}. Please update the testdata.")
}
} catch (e: Throwable) {
if (vm.shortName !in failsIn) {
return@map e
}
}
null
}
when (exceptions.size) {
0 -> {} // Everything OK
1 -> {
throw exceptions.single()
}
else -> {
throw AssertionError("Failed with several exceptions. Look at suppressed exceptions below.").apply {
exceptions.forEach { addSuppressed(it) }
}
}
}
if (mode == "dce") {
checkExpectedOutputSize(testFile, dir)
}
}
writeToFilesAndRunTest("dev", compilerResult)
writeToFilesAndRunTest("dce", compilerResultWithDCE)
}
}
private fun getOutputDir(file: File, testGroupOutputDir: File = testGroupOutputDirForCompilation): File {
val stopFile = File(pathToTestDir)
return generateSequence(file.parentFile) { it.parentFile }
.takeWhile { it != stopFile }
.map { it.name }
.toList().asReversed()
.fold(testGroupOutputDir, ::File)
}
private fun createConfig(languageVersionSettings: LanguageVersionSettings?): JsConfig {
val configuration = environment.configuration.copy()
configuration.put(CommonConfigurationKeys.MODULE_NAME, TEST_MODULE)
configuration.put(JSConfigurationKeys.WASM_ENABLE_ARRAY_RANGE_CHECKS, true)
configuration.put(JSConfigurationKeys.WASM_ENABLE_ASSERTS, true)
configuration.put(JSConfigurationKeys.MODULE_KIND, ModuleKind.ES)
configuration.languageVersionSettings = languageVersionSettings
?: LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE, specificFeatures = extraLanguageFeatures)
return JsConfig(project, configuration, CompilerEnvironment, null, null)
}
@OptIn(ObsoleteTestInfrastructure::class)
private inner class TestFileFactoryImpl : TestFiles.TestFileFactoryNoModules<TestFile>(), Closeable {
override fun create(fileName: String, text: String, directives: Directives): TestFile {
val ktFile = KtPsiFactory(project).createFile(text)
val boxFunction = ktFile.declarations.find { it is KtNamedFunction && it.name == TEST_FUNCTION }
if (boxFunction != null) {
testPackage = ktFile.packageFqName.asString()
if (testPackage?.isEmpty() == true) {
testPackage = null
}
}
val languageVersionSettings = parseLanguageVersionSettings(directives, extraLanguageFeatures)
val temporaryFile = File(tmpDir, "WASM_TEST/$fileName")
KtTestUtil.mkdirs(temporaryFile.parentFile)
temporaryFile.writeText(text, Charsets.UTF_8)
return TestFile(temporaryFile.absolutePath, languageVersionSettings)
}
var testPackage: String? = null
val tmpDir = KtTestUtil.tmpDir("wasm-tests")
override fun close() {
FileUtil.delete(tmpDir)
}
}
private class TestFile(val fileName: String, val languageVersionSettings: LanguageVersionSettings?)
override fun createEnvironment() =
KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
private fun KotlinTestWithEnvironment.createPsiFile(fileName: String): KtFile {
val psiManager = PsiManager.getInstance(project)
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val file = fileSystem.findFileByPath(fileName) ?: error("File not found: $fileName")
return psiManager.findFile(file) as KtFile
}
private fun KotlinTestWithEnvironment.createPsiFiles(fileNames: List<String>): List<KtFile> {
return fileNames.map { this@createPsiFiles.createPsiFile(it) }
}
companion object {
const val TEST_MODULE = "main"
private const val TEST_FUNCTION = "box"
}
}
@@ -0,0 +1,47 @@
/*
* 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.wasm.test
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.test.directives.JsEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.AdditionalSourceProvider
import org.jetbrains.kotlin.test.services.TestServices
import java.io.File
import java.io.FileFilter
class WasmAdditionalSourceProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
if (JsEnvironmentConfigurationDirectives.NO_COMMON_FILES in module.directives) return emptyList()
return getAdditionalKotlinFiles(module.files.first().originalFile.parent).map { it.toTestFile() }
}
companion object {
private const val COMMON_FILES_NAME = "_common"
private const val COMMON_FILES_DIR = "_commonFiles/"
private const val COMMON_FILES_DIR_PATH = "js/js.translator/testData/$COMMON_FILES_DIR"
private fun getFilesInDirectoryByExtension(directory: String, extension: String): List<String> {
val dir = File(directory)
if (!dir.isDirectory) return emptyList()
return dir.listFiles(FileFilter { it.extension == extension })?.map { it.absolutePath } ?: emptyList()
}
private fun getAdditionalFiles(directory: String, extension: String): List<File> {
val globalCommonFiles = getFilesInDirectoryByExtension(COMMON_FILES_DIR_PATH, extension).map { File(it) }
val localCommonFilePath = "$directory/$COMMON_FILES_NAME.$extension"
val localCommonFile = File(localCommonFilePath).takeIf { it.exists() } ?: return globalCommonFiles
return globalCommonFiles + localCommonFile
}
fun getAdditionalKotlinFiles(directory: String): List<File> {
return getAdditionalFiles(directory, KotlinFileType.EXTENSION)
}
}
}
@@ -0,0 +1,21 @@
/*
* 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.wasm.test
import org.jetbrains.kotlin.test.WrappedException
import org.jetbrains.kotlin.test.model.AfterAnalysisChecker
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.moduleStructure
class WasmFailingTestSuppressor(testServices: TestServices) : AfterAnalysisChecker(testServices) {
override fun suppressIfNeeded(failedAssertions: List<WrappedException>): List<WrappedException> {
val testFile = testServices.moduleStructure.originalTestDataFiles.first()
val failFile = testFile.parentFile.resolve("${testFile.name}.fail").takeIf { it.exists() }
?: return failedAssertions
if (failedAssertions.any { it is WrappedException.FromFacade }) return emptyList()
return failedAssertions + AssertionError("Fail file exists but no exception was thrown. Please remove ${failFile.name}").wrap()
}
}
@@ -1,34 +0,0 @@
/*
* 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.wasm.test
import org.jetbrains.kotlin.wasm.test.BasicWasmBoxTest
abstract class AbstractIrCodegenBoxWasmTest : BasicWasmBoxTest(
"compiler/testData/codegen/box/",
"codegen/wasmBox/"
)
abstract class AbstractIrCodegenBoxInlineWasmTest : BasicWasmBoxTest(
"compiler/testData/codegen/boxInline/",
"codegen/wasmBoxInline/"
)
abstract class AbstractIrCodegenWasmJsInteropWasmTest : BasicWasmBoxTest(
"compiler/testData/codegen/wasmJsInterop",
"codegen/wasmJsInteropJs"
)
abstract class AbstractJsTranslatorWasmTest : BasicWasmBoxTest(
"js/js.translator/testData/box/",
"js.translator/wasmBox"
)
abstract class AbstractJsTranslatorUnitWasmTest : BasicWasmBoxTest(
"js/js.translator/testData/box/",
"js.translator/wasmBox",
startUnitTests = true
)
@@ -0,0 +1,123 @@
/*
* 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.wasm.test.converters
import org.jetbrains.kotlin.backend.common.CommonKLibResolver
import org.jetbrains.kotlin.backend.common.actualizer.IrActualizer
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticReporterFactory
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.ir.backend.js.JsFactories
import org.jetbrains.kotlin.ir.backend.js.resolverLogger
import org.jetbrains.kotlin.ir.backend.js.serializeModuleIntoKlib
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.IrMessageLogger
import org.jetbrains.kotlin.library.KotlinAbiVersion
import org.jetbrains.kotlin.storage.LockBasedStorageManager
import org.jetbrains.kotlin.test.backend.ir.IrBackendFacade
import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
import org.jetbrains.kotlin.test.frontend.classic.ModuleDescriptorProvider
import org.jetbrains.kotlin.test.frontend.classic.moduleDescriptorProvider
import org.jetbrains.kotlin.test.frontend.fir.getAllWasmDependenciesPaths
import org.jetbrains.kotlin.test.frontend.fir.resolveLibraries
import org.jetbrains.kotlin.test.model.ArtifactKinds
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.FrontendKinds
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfigurator
import java.io.File
class FirWasmKlibBackendFacade(
testServices: TestServices,
private val firstTimeCompilation: Boolean
) : IrBackendFacade<BinaryArtifacts.KLib>(testServices, ArtifactKinds.KLib) {
override val additionalServices: List<ServiceRegistrationData>
get() = listOf(service(::ModuleDescriptorProvider))
constructor(testServices: TestServices) : this(testServices, firstTimeCompilation = true)
override fun shouldRunAnalysis(module: TestModule): Boolean {
return module.backendKind == inputKind
}
override fun transform(module: TestModule, inputArtifact: IrBackendInput): BinaryArtifacts.KLib {
require(inputArtifact is IrBackendInput.WasmBackendInput) {
"FirWasmKlibBackendFacade expects IrBackendInput.WasmBackendInput as input"
}
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
val outputFile = WasmEnvironmentConfigurator.getWasmKlibArtifactPath(testServices, module.name)
// TODO: consider avoiding repeated libraries resolution
val libraries = resolveLibraries(configuration, getAllWasmDependenciesPaths(module, testServices))
// TODO: find out how to pass diagnostics to the test infra in this case
val diagnosticReporter = DiagnosticReporterFactory.createReporter()
if (firstTimeCompilation) {
val irActualizedResult =
if (module.frontendKind == FrontendKinds.FIR && module.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects)) {
IrActualizer.actualize(
inputArtifact.irModuleFragment,
inputArtifact.dependentIrModuleFragments,
diagnosticReporter,
IrTypeSystemContextImpl(inputArtifact.irModuleFragment.irBuiltins),
configuration.languageVersionSettings
)
} else {
null
}
serializeModuleIntoKlib(
configuration[CommonConfigurationKeys.MODULE_NAME]!!,
configuration,
configuration.get(IrMessageLogger.IR_MESSAGE_LOGGER) ?: IrMessageLogger.None,
inputArtifact.sourceFiles,
klibPath = outputFile,
libraries.map { it.library },
inputArtifact.irModuleFragment,
inputArtifact.expectDescriptorToSymbol,
cleanFiles = inputArtifact.icData,
nopack = true,
perFile = false,
containsErrorCode = inputArtifact.hasErrors,
abiVersion = KotlinAbiVersion.CURRENT, // TODO get from test file data
jsOutputName = null
) {
inputArtifact.serializeSingleFile(it, irActualizedResult)
}
}
// TODO: consider avoiding repeated libraries resolution
val lib = CommonKLibResolver.resolve(
getAllWasmDependenciesPaths(module, testServices) + listOf(outputFile),
configuration.resolverLogger
).getFullResolvedList().last().library
val moduleDescriptor = JsFactories.DefaultDeserializedDescriptorFactory.createDescriptorOptionalBuiltIns(
lib,
configuration.languageVersionSettings,
LockBasedStorageManager("ModulesStructure"),
inputArtifact.irModuleFragment.descriptor.builtIns,
packageAccessHandler = null,
lookupTracker = LookupTracker.DO_NOTHING
)
moduleDescriptor.setDependencies(
inputArtifact.irModuleFragment.descriptor.allDependencyModules.filterIsInstance<ModuleDescriptorImpl>() + moduleDescriptor
)
testServices.moduleDescriptorProvider.replaceModuleDescriptorForModule(module, moduleDescriptor)
testServices.libraryProvider.setDescriptorAndLibraryByName(outputFile, moduleDescriptor, lib)
return BinaryArtifacts.KLib(File(outputFile))
}
}
@@ -0,0 +1,139 @@
/*
* 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.wasm.test.converters
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
import org.jetbrains.kotlin.backend.wasm.compileToLoweredIr
import org.jetbrains.kotlin.backend.wasm.compileWasm
import org.jetbrains.kotlin.backend.wasm.dce.eliminateDeadDeclarations
import org.jetbrains.kotlin.backend.wasm.wasmPhases
import org.jetbrains.kotlin.ir.backend.js.MainModule
import org.jetbrains.kotlin.ir.backend.js.ModulesStructure
import org.jetbrains.kotlin.ir.backend.js.dce.dumpDeclarationIrSizesIfNeed
import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl
import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageConfig
import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageLogLevel
import org.jetbrains.kotlin.ir.linkage.partial.PartialLinkageMode
import org.jetbrains.kotlin.ir.linkage.partial.setupPartialLinkageConfig
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.test.DebugMode
import org.jetbrains.kotlin.test.model.AbstractTestFacade
import org.jetbrains.kotlin.test.model.ArtifactKinds
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.*
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfigurator
import org.jetbrains.kotlin.wasm.test.handlers.getWasmTestOutputDirectory
import java.io.File
class WasmBackendFacade(
private val testServices: TestServices
) : AbstractTestFacade<BinaryArtifacts.KLib, BinaryArtifacts.Wasm>() {
override val inputKind = ArtifactKinds.KLib
override val outputKind = ArtifactKinds.Wasm
override fun transform(module: TestModule, inputArtifact: BinaryArtifacts.KLib): BinaryArtifacts.Wasm? {
val configuration = testServices.compilerConfigurationProvider.getCompilerConfiguration(module)
// Enforce PL with the ERROR log level to fail any tests where PL detected any incompatibilities.
configuration.setupPartialLinkageConfig(PartialLinkageConfig(PartialLinkageMode.ENABLE, PartialLinkageLogLevel.ERROR))
val isMainModule = WasmEnvironmentConfigurator.isMainModule(module, testServices)
if (!isMainModule) return null
val debugMode = DebugMode.fromSystemProperty("kotlin.wasm.debugMode")
val phaseConfig = if (debugMode >= DebugMode.SUPER_DEBUG) {
val outputDirBase = testServices.getWasmTestOutputDirectory()
val dumpOutputDir = File(outputDirBase, "irdump")
println("\n ------ Dumping phases to file://${dumpOutputDir.absolutePath}")
PhaseConfig(
wasmPhases,
dumpToDirectory = dumpOutputDir.path,
toDumpStateAfter = wasmPhases.toPhaseMap().values.toSet(),
)
} else {
PhaseConfig(wasmPhases)
}
val libraries = listOf(
System.getProperty("kotlin.wasm.stdlib.path")!!,
System.getProperty("kotlin.wasm.kotlin.test.path")!!
) + WasmEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).map { it.key.libraryFile.canonicalPath }
val friendLibraries = emptyList<String>()
val mainModule = MainModule.Klib(inputArtifact.outputFile.absolutePath)
val project = testServices.compilerConfigurationProvider.getProject(module)
val moduleStructure = ModulesStructure(
project,
mainModule,
configuration,
libraries + mainModule.libPath,
friendLibraries
)
val testPackage = extractTestPackage(testServices)
val (allModules, backendContext) = compileToLoweredIr(
depsDescriptors = moduleStructure,
phaseConfig = phaseConfig,
irFactory = IrFactoryImpl,
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, "box"))),
propertyLazyInitialization = true,
)
val generateWat = debugMode >= DebugMode.DEBUG
val baseFileName = "index"
val compilerResult = compileWasm(
allModules = allModules,
backendContext = backendContext,
baseFileName = baseFileName,
emitNameSection = true,
allowIncompleteImplementations = false,
generateWat = generateWat,
)
eliminateDeadDeclarations(allModules, backendContext)
dumpDeclarationIrSizesIfNeed(System.getProperty("kotlin.wasm.dump.declaration.ir.size.to.file"), allModules)
val compilerResultWithDCE = compileWasm(
allModules = allModules,
backendContext = backendContext,
baseFileName = baseFileName,
emitNameSection = true,
allowIncompleteImplementations = true,
generateWat = generateWat,
)
return BinaryArtifacts.Wasm(
compilerResult,
compilerResultWithDCE
)
}
override fun shouldRunAnalysis(module: TestModule): Boolean {
return WasmEnvironmentConfigurator.isMainModule(module, testServices)
}
}
fun extractTestPackage(testServices: TestServices): String? {
val ktFiles = testServices.moduleStructure.modules.flatMap { module ->
module.files
.filter { it.isKtFile }
.map {
val project = testServices.compilerConfigurationProvider.getProject(module)
testServices.sourceFileProvider.getKtFileForSourceFile(it, project)
}
}
val fileWithBoxFunction = ktFiles.find { file ->
file.declarations.find { it is KtNamedFunction && it.name == "box" } != null
} ?: return null
return fileWithBoxFunction.packageFqName.asString().takeIf { it.isNotEmpty() }
}
@@ -0,0 +1,19 @@
/*
* 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.wasm.test.handlers
import org.jetbrains.kotlin.test.backend.handlers.WasmBinaryArtifactHandler
import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.TestServices
abstract class AbstractWasmArtifactsCollector(testServices: TestServices) : WasmBinaryArtifactHandler(testServices) {
val modulesToArtifact = mutableMapOf<TestModule, BinaryArtifacts.Wasm>()
override fun processModule(module: TestModule, info: BinaryArtifacts.Wasm) {
modulesToArtifact[module] = info
}
}
@@ -0,0 +1,255 @@
/*
* 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.wasm.test.handlers
import org.jetbrains.kotlin.backend.wasm.WasmCompilerResult
import org.jetbrains.kotlin.backend.wasm.writeCompilationResult
import org.jetbrains.kotlin.js.JavaScript
import org.jetbrains.kotlin.test.DebugMode
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.directives.WasmEnvironmentConfigurationDirectives
import org.jetbrains.kotlin.test.directives.WasmEnvironmentConfigurationDirectives.RUN_UNIT_TESTS
import org.jetbrains.kotlin.test.model.TestFile
import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlin.test.services.moduleStructure
import org.jetbrains.kotlin.wasm.test.tools.WasmVM
import java.io.File
class WasmBoxRunner(
testServices: TestServices
) : AbstractWasmArtifactsCollector(testServices) {
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {
if (!someAssertionWasFailed) {
runWasmCode()
}
}
private fun runWasmCode() {
val artifacts = modulesToArtifact.values.single()
val baseFileName = "index"
val outputDirBase = testServices.getWasmTestOutputDirectory()
val jsFiles = mutableListOf<AdditionalFile>()
val mjsFiles = mutableListOf<AdditionalFile>()
var entryMjs: String? = "test.mjs"
testServices.moduleStructure.modules.forEach { m ->
m.files.forEach { file: TestFile ->
val name = file.name
when {
name.endsWith(".js") ->
jsFiles += AdditionalFile(file.name, file.originalContent)
name.endsWith(".mjs") -> {
mjsFiles += AdditionalFile(file.name, file.originalContent)
if (name == "entry.mjs") {
entryMjs = name
}
}
}
}
}
val originalFile = testServices.moduleStructure.originalTestDataFiles.first()
originalFile.parentFile.resolve(originalFile.nameWithoutExtension + JavaScript.DOT_EXTENSION)
.takeIf { it.exists() }
?.let {
jsFiles += AdditionalFile(it.name, it.readText())
}
originalFile.parentFile.resolve(originalFile.nameWithoutExtension + JavaScript.DOT_MODULE_EXTENSION)
.takeIf { it.exists() }
?.let {
mjsFiles += AdditionalFile(it.name, it.readText())
}
val debugMode = DebugMode.fromSystemProperty("kotlin.js.debugMode")
val startUnitTests = RUN_UNIT_TESTS in testServices.moduleStructure.allDirectives
val testJsQuiet = """
let actualResult;
try {
// Use "dynamic import" to catch exception happened during JS & Wasm modules initialization
let jsModule = await import('./index.mjs');
let wasmExports = jsModule.default;
${if (startUnitTests) "wasmExports.startUnitTests();" else ""}
actualResult = wasmExports.box();
} catch(e) {
console.log('Failed with exception!')
console.log('Message: ' + e.message)
console.log('Name: ' + e.name)
console.log('Stack:')
console.log(e.stack)
}
if (actualResult !== "OK")
throw `Wrong box result '${'$'}{actualResult}'; Expected "OK"`;
""".trimIndent()
val testJsVerbose = testJsQuiet + """
console.log('test passed');
""".trimIndent()
val testJs = if (debugMode >= DebugMode.DEBUG) testJsVerbose else testJsQuiet
fun checkExpectedOutputSize(testFileContent: String, testDir: File) {
val expectedSizes =
InTextDirectivesUtils.findListWithPrefixes(testFileContent, "// WASM_DCE_EXPECTED_OUTPUT_SIZE: ")
.map {
val i = it.indexOf(' ')
val extension = it.substring(0, i)
val size = it.substring(i + 1)
extension.trim().lowercase() to size.filter(Char::isDigit).toInt()
}
val filesByExtension = testDir.listFiles()?.groupBy { it.extension }.orEmpty()
val errors = expectedSizes.mapNotNull { (extension, expectedSize) ->
val totalSize = filesByExtension[extension].orEmpty().sumOf { it.length() }
val thresholdPercent = 1
val thresholdInBytes = expectedSize * thresholdPercent / 100
val expectedMinSize = expectedSize - thresholdInBytes
val expectedMaxSize = expectedSize + thresholdInBytes
val diff = totalSize - expectedSize
val message = "Total size of $extension files is $totalSize," +
" but expected $expectedSize$thresholdInBytes [$expectedMinSize .. $expectedMaxSize]." +
" Diff: $diff (${diff * 100 / expectedSize}%)"
if (debugMode >= DebugMode.DEBUG) {
println(" ------ $message")
}
if (totalSize !in expectedMinSize..expectedMaxSize) message else null
}
if (errors.isNotEmpty()) throw AssertionError(errors.joinToString("\n"))
}
fun writeToFilesAndRunTest(mode: String, res: WasmCompilerResult) {
val dir = File(outputDirBase, mode)
dir.mkdirs()
writeCompilationResult(res, dir, baseFileName)
File(dir, "test.mjs").writeText(testJs)
for (mjsFile: AdditionalFile in mjsFiles) {
File(dir, mjsFile.name).writeText(mjsFile.content)
}
val jsFilePaths = mutableListOf<String>()
for (jsFile: AdditionalFile in jsFiles) {
val file = File(dir, jsFile.name)
file.writeText(jsFile.content)
jsFilePaths += file.canonicalPath
}
if (debugMode >= DebugMode.DEBUG) {
File(dir, "index.html").writeText(
"""
<!DOCTYPE html>
<html lang="en">
<body>
<span id="test">UNKNOWN</span>
<script type="module">
let test = document.getElementById("test")
try {
await import("./test.mjs");
test.style.backgroundColor = "#0f0";
test.textContent = "OK"
} catch(e) {
test.style.backgroundColor = "#f00";
test.textContent = "NOT OK"
throw e;
}
</script>
</body>
</html>
""".trimIndent()
)
val path = dir.absolutePath
println(" ------ $mode Wat file://$path/index.wat")
println(" ------ $mode Wasm file://$path/index.wasm")
println(" ------ $mode JS file://$path/index.uninstantiated.mjs")
println(" ------ $mode JS file://$path/index.mjs")
println(" ------ $mode Test file://$path/test.mjs")
val projectName = "kotlin"
println(" ------ $mode HTML http://0.0.0.0:63342/$projectName/${dir.path}/index.html")
for (mjsFile: AdditionalFile in mjsFiles) {
println(" ------ $mode External ESM file://$path/${mjsFile.name}")
}
}
val testFileText = originalFile.readText()
val failsIn: List<String> = InTextDirectivesUtils.findListWithPrefixes(testFileText, "// WASM_FAILS_IN: ")
val exceptions = listOf(WasmVM.V8, WasmVM.SpiderMonkey).mapNotNull map@{ vm ->
try {
if (debugMode >= DebugMode.DEBUG) {
println(" ------ Run in ${vm.name}" + if (vm.shortName in failsIn) " (expected to fail)" else "")
}
vm.run(
"./${entryMjs}",
jsFilePaths,
workingDirectory = dir
)
if (vm.shortName in failsIn) {
return@map AssertionError("The test expected to fail in ${vm.name}. Please update the testdata.")
}
} catch (e: Throwable) {
if (vm.shortName !in failsIn) {
return@map e
}
}
null
}
when (exceptions.size) {
0 -> {} // Everything OK
1 -> {
throw exceptions.single()
}
else -> {
throw AssertionError("Failed with several exceptions. Look at suppressed exceptions below.").apply {
exceptions.forEach { addSuppressed(it) }
}
}
}
if (mode == "dce") {
checkExpectedOutputSize(testFileText, dir)
}
}
writeToFilesAndRunTest("dev", artifacts.compilerResult)
writeToFilesAndRunTest("dce", artifacts.compilerResultWithDCE)
}
private class AdditionalFile(val name: String, val content: String)
}
fun TestServices.getWasmTestOutputDirectory(): File {
val originalFile = moduleStructure.originalTestDataFiles.first()
val allDirectives = moduleStructure.allDirectives
val pathToRootOutputDir = allDirectives[WasmEnvironmentConfigurationDirectives.PATH_TO_ROOT_OUTPUT_DIR].first()
val testGroupDirPrefix = allDirectives[WasmEnvironmentConfigurationDirectives.TEST_GROUP_OUTPUT_DIR_PREFIX].first()
val pathToTestDir = allDirectives[WasmEnvironmentConfigurationDirectives.PATH_TO_TEST_DIR].first()
val testGroupOutputDir = File(File(pathToRootOutputDir, "out"), testGroupDirPrefix)
val stopFile = File(pathToTestDir)
return generateSequence(originalFile.parentFile) { it.parentFile }
.takeWhile { it != stopFile }
.map { it.name }
.toList().asReversed()
.fold(testGroupOutputDir, ::File)
.let { File(it, originalFile.nameWithoutExtension) }
}
@@ -6,12 +6,11 @@
package org.jetbrains.kotlin.wasm.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
@@ -20,121 +19,139 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/boxWasmJsInterop")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IrCodegenWasmJsInteropWasmTestGenerated extends AbstractIrCodegenWasmJsInteropWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class FirWasmCodegenWasmJsInteropTestGenerated extends AbstractFirWasmCodegenWasmJsInteropTest {
@Test
public void testAllFilesPresentInBoxWasmJsInterop() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("callingWasmDirectly.kt")
public void testCallingWasmDirectly() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/callingWasmDirectly.kt");
}
@Test
@TestMetadata("defaultValues.kt")
public void testDefaultValues() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/defaultValues.kt");
}
@Test
@TestMetadata("externalTypeOperators.kt")
public void testExternalTypeOperators() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/externalTypeOperators.kt");
}
@Test
@TestMetadata("externals.kt")
public void testExternals() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/externals.kt");
}
@Test
@TestMetadata("functionTypes.kt")
public void testFunctionTypes() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/functionTypes.kt");
}
@Test
@TestMetadata("imperativeWrapperInitialised.kt")
public void testImperativeWrapperInitialised() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/imperativeWrapperInitialised.kt");
}
@Test
@TestMetadata("imperativeWrapperUninitialised.kt")
public void testImperativeWrapperUninitialised() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/imperativeWrapperUninitialised.kt");
}
@Test
@TestMetadata("jsCode.kt")
public void testJsCode() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsCode.kt");
}
@Test
@TestMetadata("jsExport.kt")
public void testJsExport() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
}
@Test
@TestMetadata("jsModule.kt")
public void testJsModule() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModule.kt");
}
@Test
@TestMetadata("jsModuleWithQualifier.kt")
public void testJsModuleWithQualifier() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModuleWithQualifier.kt");
}
@Test
@TestMetadata("jsQualifier.kt")
public void testJsQualifier() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsQualifier.kt");
}
@Test
@TestMetadata("jsToKotlinAdapters.kt")
public void testJsToKotlinAdapters() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt");
}
@Test
@TestMetadata("jsTypes.kt")
public void testJsTypes() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsTypes.kt");
}
@Test
@TestMetadata("kotlinToJsAdapters.kt")
public void testKotlinToJsAdapters() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt");
}
@Test
@TestMetadata("lambdaAdapterNameClash.kt")
public void testLambdaAdapterNameClash() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/lambdaAdapterNameClash.kt");
}
@Test
@TestMetadata("longStrings.kt")
public void testLongStrings() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/longStrings.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/nameClash.kt");
}
@Test
@TestMetadata("nullableExternRefs.kt")
public void testNullableExternRefs() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt");
}
@Test
@TestMetadata("types.kt")
public void testTypes() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/types.kt");
}
@Test
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/vararg.kt");
}
@Test
@TestMetadata("wasmImport.kt")
public void testWasmImport() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/wasmImport.kt");
@@ -0,0 +1,474 @@
/*
* 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.wasm.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateWasmTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
public class FirWasmJsTranslatorTestGenerated extends AbstractFirWasmJsTranslatorTest {
@Nested
@TestMetadata("js/js.translator/testData/box/main")
@TestDataPath("$PROJECT_ROOT")
public class Main {
@Test
public void testAllFilesPresentInMain() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/main"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("differentMains.kt")
public void testDifferentMains() throws Exception {
runTest("js/js.translator/testData/box/main/differentMains.kt");
}
@Test
@TestMetadata("incremental.kt")
public void testIncremental() throws Exception {
runTest("js/js.translator/testData/box/main/incremental.kt");
}
@Test
@TestMetadata("noArgs.kt")
public void testNoArgs() throws Exception {
runTest("js/js.translator/testData/box/main/noArgs.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/main/simple.kt");
}
@Test
@TestMetadata("suspendMain.kt")
public void testSuspendMain() throws Exception {
runTest("js/js.translator/testData/box/main/suspendMain.kt");
}
@Test
@TestMetadata("suspendMainNoArgs.kt")
public void testSuspendMainNoArgs() throws Exception {
runTest("js/js.translator/testData/box/main/suspendMainNoArgs.kt");
}
@Test
@TestMetadata("suspendMainThrows.kt")
public void testSuspendMainThrows() throws Exception {
runTest("js/js.translator/testData/box/main/suspendMainThrows.kt");
}
@Test
@TestMetadata("twoMains.kt")
public void testTwoMains() throws Exception {
runTest("js/js.translator/testData/box/main/twoMains.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/native")
@TestDataPath("$PROJECT_ROOT")
public class Native {
@Test
@TestMetadata("accessToCompanionObjectFromInlineFun.kt")
public void testAccessToCompanionObjectFromInlineFun() throws Exception {
runTest("js/js.translator/testData/box/native/accessToCompanionObjectFromInlineFun.kt");
}
@Test
public void testAllFilesPresentInNative() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/native"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("castToNativeClassChecked.kt")
public void testCastToNativeClassChecked() throws Exception {
runTest("js/js.translator/testData/box/native/castToNativeClassChecked.kt");
}
@Test
@TestMetadata("castToNativeInterface.kt")
public void testCastToNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/castToNativeInterface.kt");
}
@Test
@TestMetadata("castToNativeInterfaceChecked.kt")
public void testCastToNativeInterfaceChecked() throws Exception {
runTest("js/js.translator/testData/box/native/castToNativeInterfaceChecked.kt");
}
@Test
@TestMetadata("castToNullableNativeInterface.kt")
public void testCastToNullableNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/castToNullableNativeInterface.kt");
}
@Test
@TestMetadata("castToTypeParamBoundedByNativeInterface.kt")
public void testCastToTypeParamBoundedByNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/castToTypeParamBoundedByNativeInterface.kt");
}
@Test
@TestMetadata("class.kt")
public void testClass() throws Exception {
runTest("js/js.translator/testData/box/native/class.kt");
}
@Test
@TestMetadata("classObject.kt")
public void testClassObject() throws Exception {
runTest("js/js.translator/testData/box/native/classObject.kt");
}
@Test
@TestMetadata("externalValWithOverridenVar.kt")
public void testExternalValWithOverridenVar() throws Exception {
runTest("js/js.translator/testData/box/native/externalValWithOverridenVar.kt");
}
@Test
@TestMetadata("kt2209.kt")
public void testKt2209() throws Exception {
runTest("js/js.translator/testData/box/native/kt2209.kt");
}
@Test
@TestMetadata("nestedElements.kt")
public void testNestedElements() throws Exception {
runTest("js/js.translator/testData/box/native/nestedElements.kt");
}
@Test
@TestMetadata("objectFunWithVararg.kt")
public void testObjectFunWithVararg() throws Exception {
runTest("js/js.translator/testData/box/native/objectFunWithVararg.kt");
}
@Test
@TestMetadata("passExtLambdaToNative.kt")
public void testPassExtLambdaToNative() throws Exception {
runTest("js/js.translator/testData/box/native/passExtLambdaToNative.kt");
}
@Test
@TestMetadata("passMemberOrExtFromNative.kt")
public void testPassMemberOrExtFromNative() throws Exception {
runTest("js/js.translator/testData/box/native/passMemberOrExtFromNative.kt");
}
@Test
@TestMetadata("passMemberOrExtToNative.kt")
public void testPassMemberOrExtToNative() throws Exception {
runTest("js/js.translator/testData/box/native/passMemberOrExtToNative.kt");
}
@Test
@TestMetadata("passTopLevelFunctionFromNative.kt")
public void testPassTopLevelFunctionFromNative() throws Exception {
runTest("js/js.translator/testData/box/native/passTopLevelFunctionFromNative.kt");
}
@Test
@TestMetadata("passTopLevelOrLocalFunctionToNative.kt")
public void testPassTopLevelOrLocalFunctionToNative() throws Exception {
runTest("js/js.translator/testData/box/native/passTopLevelOrLocalFunctionToNative.kt");
}
@Test
@TestMetadata("privateExternal.kt")
public void testPrivateExternal() throws Exception {
runTest("js/js.translator/testData/box/native/privateExternal.kt");
}
@Test
@TestMetadata("safeCastToNativeInterface.kt")
public void testSafeCastToNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/safeCastToNativeInterface.kt");
}
@Test
@TestMetadata("secondaryConstructor.kt")
public void testSecondaryConstructor() throws Exception {
runTest("js/js.translator/testData/box/native/secondaryConstructor.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/native/simple.kt");
}
@Test
@TestMetadata("simpleUndefined.kt")
public void testSimpleUndefined() throws Exception {
runTest("js/js.translator/testData/box/native/simpleUndefined.kt");
}
@Test
@TestMetadata("useClassFromInlineFun.kt")
public void testUseClassFromInlineFun() throws Exception {
runTest("js/js.translator/testData/box/native/useClassFromInlineFun.kt");
}
@Test
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("js/js.translator/testData/box/native/vararg.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules")
@TestDataPath("$PROJECT_ROOT")
public class EsModules {
@Test
public void testAllFilesPresentInEsModules() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true, "jsExport", "native", "export", "crossModuleRef", "crossModuleRefPerFile", "crossModuleRefPerModule");
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/incremental")
@TestDataPath("$PROJECT_ROOT")
public class Incremental {
@Test
public void testAllFilesPresentInIncremental() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("jsModule.kt")
public void testJsModule() throws Exception {
runTest("js/js.translator/testData/box/esModules/incremental/jsModule.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/inline")
@TestDataPath("$PROJECT_ROOT")
public class Inline {
@Test
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/jsModule")
@TestDataPath("$PROJECT_ROOT")
public class JsModule {
@Test
public void testAllFilesPresentInJsModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("externalClass.kt")
public void testExternalClass() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalClass.kt");
}
@Test
@TestMetadata("externalClassNameClash.kt")
public void testExternalClassNameClash() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt");
}
@Test
@TestMetadata("externalFunction.kt")
public void testExternalFunction() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalFunction.kt");
}
@Test
@TestMetadata("externalFunctionNameClash.kt")
public void testExternalFunctionNameClash() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt");
}
@Test
@TestMetadata("externalObject.kt")
public void testExternalObject() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalObject.kt");
}
@Test
@TestMetadata("externalPackage.kt")
public void testExternalPackage() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalPackage.kt");
}
@Test
@TestMetadata("externalPackageInDifferentFile.kt")
public void testExternalPackageInDifferentFile() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt");
}
@Test
@TestMetadata("externalProperty.kt")
public void testExternalProperty() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalProperty.kt");
}
@Test
@TestMetadata("interfaces.kt")
public void testInterfaces() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/interfaces.kt");
}
@Test
@TestMetadata("topLevelVarargFun.kt")
public void testTopLevelVarargFun() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/jsName")
@TestDataPath("$PROJECT_ROOT")
public class JsName {
@Test
public void testAllFilesPresentInJsName() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsName"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("defaultJsName.kt")
public void testDefaultJsName() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsName/defaultJsName.kt");
}
@Test
@TestMetadata("jsTopLevelClashes.kt")
public void testJsTopLevelClashes() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt");
}
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/jsQualifier")
@TestDataPath("$PROJECT_ROOT")
public class JsQualifier {
@Test
public void testAllFilesPresentInJsQualifier() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/jsQualifier"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("classes.kt")
public void testClasses() throws Exception {
runTest("js/js.translator/testData/box/jsQualifier/classes.kt");
}
@Test
@TestMetadata("interfaces.kt")
public void testInterfaces() throws Exception {
runTest("js/js.translator/testData/box/jsQualifier/interfaces.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/jsQualifier/simple.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/reflection")
@TestDataPath("$PROJECT_ROOT")
public class Reflection {
@Test
public void testAllFilesPresentInReflection() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/reflection"), Pattern.compile("^(findAssociatedObject(InSeparatedFile)?)\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("findAssociatedObject.kt")
public void testFindAssociatedObject() throws Exception {
runTest("js/js.translator/testData/box/reflection/findAssociatedObject.kt");
}
@Test
@TestMetadata("findAssociatedObjectInSeparatedFile.kt")
public void testFindAssociatedObjectInSeparatedFile() throws Exception {
runTest("js/js.translator/testData/box/reflection/findAssociatedObjectInSeparatedFile.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/kotlin.test")
@TestDataPath("$PROJECT_ROOT")
public class Kotlin_test {
@Test
public void testAllFilesPresentInKotlin_test() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/kotlin.test"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("beforeAfter.kt")
public void testBeforeAfter() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/beforeAfter.kt");
}
@Test
@TestMetadata("ignore.kt")
public void testIgnore() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/ignore.kt");
}
@Test
@TestMetadata("illegalParameters.kt")
public void testIllegalParameters() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/illegalParameters.kt");
}
@Test
@TestMetadata("incremental.kt")
public void testIncremental() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/incremental.kt");
}
@Test
@TestMetadata("inherited.kt")
public void testInherited() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/inherited.kt");
}
@Test
@TestMetadata("mpp.kt")
public void testMpp() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/mpp.kt");
}
@Test
@TestMetadata("nested.kt")
public void testNested() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/nested.kt");
}
@Test
@TestMetadata("returnTestResult.kt")
public void testReturnTestResult() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/returnTestResult.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/simple.kt");
}
}
}
@@ -1,77 +0,0 @@
/*
* 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.wasm.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
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.GenerateWasmTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("js/js.translator/testData/box/kotlin.test")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class JsTranslatorUnitWasmTestGenerated extends AbstractJsTranslatorUnitWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInKotlin_test() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/kotlin.test"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@TestMetadata("beforeAfter.kt")
public void testBeforeAfter() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/beforeAfter.kt");
}
@TestMetadata("ignore.kt")
public void testIgnore() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/ignore.kt");
}
@TestMetadata("illegalParameters.kt")
public void testIllegalParameters() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/illegalParameters.kt");
}
@TestMetadata("incremental.kt")
public void testIncremental() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/incremental.kt");
}
@TestMetadata("inherited.kt")
public void testInherited() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/inherited.kt");
}
@TestMetadata("mpp.kt")
public void testMpp() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/mpp.kt");
}
@TestMetadata("nested.kt")
public void testNested() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/nested.kt");
}
@TestMetadata("returnTestResult.kt")
public void testReturnTestResult() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/returnTestResult.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/simple.kt");
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,159 @@
/*
* 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.wasm.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateWasmTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/codegen/boxWasmJsInterop")
@TestDataPath("$PROJECT_ROOT")
public class K1WasmCodegenWasmJsInteropTestGenerated extends AbstractK1WasmCodegenWasmJsInteropTest {
@Test
public void testAllFilesPresentInBoxWasmJsInterop() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("callingWasmDirectly.kt")
public void testCallingWasmDirectly() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/callingWasmDirectly.kt");
}
@Test
@TestMetadata("defaultValues.kt")
public void testDefaultValues() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/defaultValues.kt");
}
@Test
@TestMetadata("externalTypeOperators.kt")
public void testExternalTypeOperators() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/externalTypeOperators.kt");
}
@Test
@TestMetadata("externals.kt")
public void testExternals() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/externals.kt");
}
@Test
@TestMetadata("functionTypes.kt")
public void testFunctionTypes() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/functionTypes.kt");
}
@Test
@TestMetadata("imperativeWrapperInitialised.kt")
public void testImperativeWrapperInitialised() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/imperativeWrapperInitialised.kt");
}
@Test
@TestMetadata("imperativeWrapperUninitialised.kt")
public void testImperativeWrapperUninitialised() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/imperativeWrapperUninitialised.kt");
}
@Test
@TestMetadata("jsCode.kt")
public void testJsCode() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsCode.kt");
}
@Test
@TestMetadata("jsExport.kt")
public void testJsExport() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsExport.kt");
}
@Test
@TestMetadata("jsModule.kt")
public void testJsModule() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModule.kt");
}
@Test
@TestMetadata("jsModuleWithQualifier.kt")
public void testJsModuleWithQualifier() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsModuleWithQualifier.kt");
}
@Test
@TestMetadata("jsQualifier.kt")
public void testJsQualifier() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsQualifier.kt");
}
@Test
@TestMetadata("jsToKotlinAdapters.kt")
public void testJsToKotlinAdapters() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsToKotlinAdapters.kt");
}
@Test
@TestMetadata("jsTypes.kt")
public void testJsTypes() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/jsTypes.kt");
}
@Test
@TestMetadata("kotlinToJsAdapters.kt")
public void testKotlinToJsAdapters() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/kotlinToJsAdapters.kt");
}
@Test
@TestMetadata("lambdaAdapterNameClash.kt")
public void testLambdaAdapterNameClash() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/lambdaAdapterNameClash.kt");
}
@Test
@TestMetadata("longStrings.kt")
public void testLongStrings() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/longStrings.kt");
}
@Test
@TestMetadata("nameClash.kt")
public void testNameClash() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/nameClash.kt");
}
@Test
@TestMetadata("nullableExternRefs.kt")
public void testNullableExternRefs() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/nullableExternRefs.kt");
}
@Test
@TestMetadata("types.kt")
public void testTypes() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/types.kt");
}
@Test
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/vararg.kt");
}
@Test
@TestMetadata("wasmImport.kt")
public void testWasmImport() throws Exception {
runTest("compiler/testData/codegen/boxWasmJsInterop/wasmImport.kt");
}
}
@@ -6,329 +6,351 @@
package org.jetbrains.kotlin.wasm.test;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.util.KtTestUtil;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateWasmTestsKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class JsTranslatorWasmTestGenerated extends AbstractJsTranslatorWasmTest {
public class K1WasmJsTranslatorTestGenerated extends AbstractK1WasmJsTranslatorTest {
@Nested
@TestMetadata("js/js.translator/testData/box/main")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Main extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class Main {
@Test
public void testAllFilesPresentInMain() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/main"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("differentMains.kt")
public void testDifferentMains() throws Exception {
runTest("js/js.translator/testData/box/main/differentMains.kt");
}
@Test
@TestMetadata("incremental.kt")
public void testIncremental() throws Exception {
runTest("js/js.translator/testData/box/main/incremental.kt");
}
@Test
@TestMetadata("noArgs.kt")
public void testNoArgs() throws Exception {
runTest("js/js.translator/testData/box/main/noArgs.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/main/simple.kt");
}
@Test
@TestMetadata("suspendMain.kt")
public void testSuspendMain() throws Exception {
runTest("js/js.translator/testData/box/main/suspendMain.kt");
}
@Test
@TestMetadata("suspendMainNoArgs.kt")
public void testSuspendMainNoArgs() throws Exception {
runTest("js/js.translator/testData/box/main/suspendMainNoArgs.kt");
}
@Test
@TestMetadata("suspendMainThrows.kt")
public void testSuspendMainThrows() throws Exception {
runTest("js/js.translator/testData/box/main/suspendMainThrows.kt");
}
@Test
@TestMetadata("twoMains.kt")
public void testTwoMains() throws Exception {
runTest("js/js.translator/testData/box/main/twoMains.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/native")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Native extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class Native {
@Test
@TestMetadata("accessToCompanionObjectFromInlineFun.kt")
public void testAccessToCompanionObjectFromInlineFun() throws Exception {
runTest("js/js.translator/testData/box/native/accessToCompanionObjectFromInlineFun.kt");
}
@Test
public void testAllFilesPresentInNative() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/native"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("castToNativeClassChecked.kt")
public void testCastToNativeClassChecked() throws Exception {
runTest("js/js.translator/testData/box/native/castToNativeClassChecked.kt");
}
@Test
@TestMetadata("castToNativeInterface.kt")
public void testCastToNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/castToNativeInterface.kt");
}
@Test
@TestMetadata("castToNativeInterfaceChecked.kt")
public void testCastToNativeInterfaceChecked() throws Exception {
runTest("js/js.translator/testData/box/native/castToNativeInterfaceChecked.kt");
}
@Test
@TestMetadata("castToNullableNativeInterface.kt")
public void testCastToNullableNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/castToNullableNativeInterface.kt");
}
@Test
@TestMetadata("castToTypeParamBoundedByNativeInterface.kt")
public void testCastToTypeParamBoundedByNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/castToTypeParamBoundedByNativeInterface.kt");
}
@Test
@TestMetadata("class.kt")
public void testClass() throws Exception {
runTest("js/js.translator/testData/box/native/class.kt");
}
@Test
@TestMetadata("classObject.kt")
public void testClassObject() throws Exception {
runTest("js/js.translator/testData/box/native/classObject.kt");
}
@Test
@TestMetadata("externalValWithOverridenVar.kt")
public void testExternalValWithOverridenVar() throws Exception {
runTest("js/js.translator/testData/box/native/externalValWithOverridenVar.kt");
}
@Test
@TestMetadata("kt2209.kt")
public void testKt2209() throws Exception {
runTest("js/js.translator/testData/box/native/kt2209.kt");
}
@Test
@TestMetadata("nestedElements.kt")
public void testNestedElements() throws Exception {
runTest("js/js.translator/testData/box/native/nestedElements.kt");
}
@Test
@TestMetadata("objectFunWithVararg.kt")
public void testObjectFunWithVararg() throws Exception {
runTest("js/js.translator/testData/box/native/objectFunWithVararg.kt");
}
@Test
@TestMetadata("passExtLambdaToNative.kt")
public void testPassExtLambdaToNative() throws Exception {
runTest("js/js.translator/testData/box/native/passExtLambdaToNative.kt");
}
@Test
@TestMetadata("passMemberOrExtFromNative.kt")
public void testPassMemberOrExtFromNative() throws Exception {
runTest("js/js.translator/testData/box/native/passMemberOrExtFromNative.kt");
}
@Test
@TestMetadata("passMemberOrExtToNative.kt")
public void testPassMemberOrExtToNative() throws Exception {
runTest("js/js.translator/testData/box/native/passMemberOrExtToNative.kt");
}
@Test
@TestMetadata("passTopLevelFunctionFromNative.kt")
public void testPassTopLevelFunctionFromNative() throws Exception {
runTest("js/js.translator/testData/box/native/passTopLevelFunctionFromNative.kt");
}
@Test
@TestMetadata("passTopLevelOrLocalFunctionToNative.kt")
public void testPassTopLevelOrLocalFunctionToNative() throws Exception {
runTest("js/js.translator/testData/box/native/passTopLevelOrLocalFunctionToNative.kt");
}
@Test
@TestMetadata("privateExternal.kt")
public void testPrivateExternal() throws Exception {
runTest("js/js.translator/testData/box/native/privateExternal.kt");
}
@Test
@TestMetadata("safeCastToNativeInterface.kt")
public void testSafeCastToNativeInterface() throws Exception {
runTest("js/js.translator/testData/box/native/safeCastToNativeInterface.kt");
}
@Test
@TestMetadata("secondaryConstructor.kt")
public void testSecondaryConstructor() throws Exception {
runTest("js/js.translator/testData/box/native/secondaryConstructor.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/native/simple.kt");
}
@Test
@TestMetadata("simpleUndefined.kt")
public void testSimpleUndefined() throws Exception {
runTest("js/js.translator/testData/box/native/simpleUndefined.kt");
}
@Test
@TestMetadata("useClassFromInlineFun.kt")
public void testUseClassFromInlineFun() throws Exception {
runTest("js/js.translator/testData/box/native/useClassFromInlineFun.kt");
}
@Test
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("js/js.translator/testData/box/native/vararg.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class EsModules extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class EsModules {
@Test
public void testAllFilesPresentInEsModules() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true, "jsExport", "native", "export", "crossModuleRef", "crossModuleRefPerFile", "crossModuleRefPerModule");
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/incremental")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Incremental extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class Incremental {
@Test
public void testAllFilesPresentInIncremental() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("jsModule.kt")
public void testJsModule() throws Exception {
runTest("js/js.translator/testData/box/esModules/incremental/jsModule.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/inline")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Inline extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class Inline {
@Test
public void testAllFilesPresentInInline() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/inline"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/jsModule")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JsModule extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class JsModule {
@Test
public void testAllFilesPresentInJsModule() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsModule"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("externalClass.kt")
public void testExternalClass() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalClass.kt");
}
@Test
@TestMetadata("externalClassNameClash.kt")
public void testExternalClassNameClash() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalClassNameClash.kt");
}
@Test
@TestMetadata("externalFunction.kt")
public void testExternalFunction() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalFunction.kt");
}
@Test
@TestMetadata("externalFunctionNameClash.kt")
public void testExternalFunctionNameClash() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalFunctionNameClash.kt");
}
@Test
@TestMetadata("externalObject.kt")
public void testExternalObject() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalObject.kt");
}
@Test
@TestMetadata("externalPackage.kt")
public void testExternalPackage() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalPackage.kt");
}
@Test
@TestMetadata("externalPackageInDifferentFile.kt")
public void testExternalPackageInDifferentFile() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalPackageInDifferentFile.kt");
}
@Test
@TestMetadata("externalProperty.kt")
public void testExternalProperty() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/externalProperty.kt");
}
@Test
@TestMetadata("interfaces.kt")
public void testInterfaces() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/interfaces.kt");
}
@Test
@TestMetadata("topLevelVarargFun.kt")
public void testTopLevelVarargFun() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsModule/topLevelVarargFun.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/esModules/jsName")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JsName extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class JsName {
@Test
public void testAllFilesPresentInJsName() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/esModules/jsName"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("defaultJsName.kt")
public void testDefaultJsName() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsName/defaultJsName.kt");
}
@Test
@TestMetadata("jsTopLevelClashes.kt")
public void testJsTopLevelClashes() throws Exception {
runTest("js/js.translator/testData/box/esModules/jsName/jsTopLevelClashes.kt");
@@ -336,54 +358,117 @@ public class JsTranslatorWasmTestGenerated extends AbstractJsTranslatorWasmTest
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/jsQualifier")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class JsQualifier extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class JsQualifier {
@Test
public void testAllFilesPresentInJsQualifier() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/jsQualifier"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("classes.kt")
public void testClasses() throws Exception {
runTest("js/js.translator/testData/box/jsQualifier/classes.kt");
}
@Test
@TestMetadata("interfaces.kt")
public void testInterfaces() throws Exception {
runTest("js/js.translator/testData/box/jsQualifier/interfaces.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/jsQualifier/simple.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/reflection")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Reflection extends AbstractJsTranslatorWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public class Reflection {
@Test
public void testAllFilesPresentInReflection() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/reflection"), Pattern.compile("^(findAssociatedObject(InSeparatedFile)?)\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("findAssociatedObject.kt")
public void testFindAssociatedObject() throws Exception {
runTest("js/js.translator/testData/box/reflection/findAssociatedObject.kt");
}
@Test
@TestMetadata("findAssociatedObjectInSeparatedFile.kt")
public void testFindAssociatedObjectInSeparatedFile() throws Exception {
runTest("js/js.translator/testData/box/reflection/findAssociatedObjectInSeparatedFile.kt");
}
}
@Nested
@TestMetadata("js/js.translator/testData/box/kotlin.test")
@TestDataPath("$PROJECT_ROOT")
public class Kotlin_test {
@Test
public void testAllFilesPresentInKotlin_test() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/box/kotlin.test"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
}
@Test
@TestMetadata("beforeAfter.kt")
public void testBeforeAfter() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/beforeAfter.kt");
}
@Test
@TestMetadata("ignore.kt")
public void testIgnore() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/ignore.kt");
}
@Test
@TestMetadata("illegalParameters.kt")
public void testIllegalParameters() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/illegalParameters.kt");
}
@Test
@TestMetadata("incremental.kt")
public void testIncremental() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/incremental.kt");
}
@Test
@TestMetadata("inherited.kt")
public void testInherited() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/inherited.kt");
}
@Test
@TestMetadata("mpp.kt")
public void testMpp() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/mpp.kt");
}
@Test
@TestMetadata("nested.kt")
public void testNested() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/nested.kt");
}
@Test
@TestMetadata("returnTestResult.kt")
public void testReturnTestResult() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/returnTestResult.kt");
}
@Test
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("js/js.translator/testData/box/kotlin.test/simple.kt");
}
}
}