From a8d0e60328f38dcbc087b780fe85aae5ab859c97 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 26 May 2021 20:05:03 +0300 Subject: [PATCH] [JS TESTS] Extend test frame with some features - Setting up specific ABI version for module - Disabling mangle verification --- .../kotlin/ir/backend/js/compiler.kt | 3 +- .../jetbrains/kotlin/backend/wasm/compiler.kt | 5 +++- .../jetbrains/kotlin/ir/backend/js/klib.kt | 19 ++++++++----- .../checkers/KotlinMultiFileTestWithJava.kt | 3 +- .../AbstractKlibBinaryCompatibilityTest.kt | 2 +- .../org/jetbrains/kotlin/test/TestFiles.java | 26 +++++++++++------ .../js/test/AbstractJsLineNumberTest.kt | 2 +- .../org/jetbrains/kotlin/js/test/ApiTest.kt | 1 + .../jetbrains/kotlin/js/test/BasicBoxTest.kt | 28 ++++++++++++++++--- .../kotlin/js/test/BasicIrBoxTest.kt | 7 +++++ 10 files changed, 70 insertions(+), 26 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt index c48aa0dcbc2..8af7076d130 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/compiler.kt @@ -53,6 +53,7 @@ fun compile( multiModule: Boolean = false, relativeRequirePath: Boolean = false, propertyLazyInitialization: Boolean, + verifySignatures: Boolean = true, legacyPropertyAccess: Boolean = false, baseClassIntoMetadata: Boolean = false, lowerPerModule: Boolean = false, @@ -60,7 +61,7 @@ fun compile( safeExternalBooleanDiagnostic: RuntimeDiagnostic? = null, ): CompilerResult { val (moduleFragment: IrModuleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer, moduleToName) = - loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory) + loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory, verifySignatures) val moduleDescriptor = moduleFragment.descriptor diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt index dace8b9002f..2a0dae91ee2 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt @@ -40,7 +40,10 @@ fun compileWasm( exportedDeclarations: Set = emptySet() ): WasmCompilerResult { val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) = - loadIr(project, mainModule, analyzer, configuration, allDependencies, friendDependencies, irFactory) + loadIr( + project, mainModule, analyzer, configuration, allDependencies, friendDependencies, + irFactory, verifySignatures = false + ) val allModules = when (mainModule) { is MainModule.SourceFiles -> dependencyModules + listOf(moduleFragment) diff --git a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt index 0ef3b3b3fee..5531d964b30 100644 --- a/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt +++ b/compiler/ir/serialization.js/src/org/jetbrains/kotlin/ir/backend/js/klib.kt @@ -15,10 +15,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContextImpl import org.jetbrains.kotlin.backend.common.lower.ExpectDeclarationRemover import org.jetbrains.kotlin.backend.common.overrides.FakeOverrideChecker -import org.jetbrains.kotlin.backend.common.serialization.DeserializationStrategy -import org.jetbrains.kotlin.backend.common.serialization.ICData -import org.jetbrains.kotlin.backend.common.serialization.KlibIrVersion -import org.jetbrains.kotlin.backend.common.serialization.knownBuiltins +import org.jetbrains.kotlin.backend.common.serialization.* import org.jetbrains.kotlin.backend.common.serialization.mangle.ManglerChecker import org.jetbrains.kotlin.backend.common.serialization.mangle.descriptor.Ir2DescriptorManglerAdapter import org.jetbrains.kotlin.backend.common.serialization.metadata.DynamicTypeDeserializer @@ -105,6 +102,7 @@ fun generateKLib( irFactory: IrFactory, outputKlibPath: String, nopack: Boolean, + verifySignatures: Boolean = true, abiVersion: KotlinAbiVersion = KotlinAbiVersion.CURRENT, jsOutputName: String? ) { @@ -170,7 +168,9 @@ fun generateKLib( val moduleFragment = psi2IrContext.generateModuleFragmentWithPlugins(project, files, irLinker, messageLogger, expectDescriptorToSymbol) - moduleFragment.acceptVoid(ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc))) + if (verifySignatures) { + moduleFragment.acceptVoid(ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc))) + } if (configuration.getBoolean(JSConfigurationKeys.FAKE_OVERRIDE_VALIDATOR)) { val fakeOverrideChecker = FakeOverrideChecker(JsManglerIr, JsManglerDesc) irLinker.modules.forEach { fakeOverrideChecker.check(it) } @@ -228,6 +228,7 @@ fun loadIr( allDependencies: KotlinLibraryResolveResult, friendDependencies: List, irFactory: IrFactory, + verifySignatures: Boolean ): IrModuleInfo { val depsDescriptors = ModulesStructure(project, mainModule, analyzer, configuration, allDependencies, friendDependencies) val errorPolicy = configuration.get(JSConfigurationKeys.ERROR_TOLERANCE_POLICY) ?: ErrorTolerancePolicy.DEFAULT @@ -259,14 +260,18 @@ fun loadIr( // TODO: not sure whether this check should be enabled by default. Add configuration key for it. val mangleChecker = ManglerChecker(JsManglerIr, Ir2DescriptorManglerAdapter(JsManglerDesc)) - moduleFragment.acceptVoid(mangleChecker) + if (verifySignatures) { + moduleFragment.acceptVoid(mangleChecker) + } if (configuration.getBoolean(JSConfigurationKeys.FAKE_OVERRIDE_VALIDATOR)) { val fakeOverrideChecker = FakeOverrideChecker(JsManglerIr, JsManglerDesc) irLinker.modules.forEach { fakeOverrideChecker.check(it) } } - irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) } + if (verifySignatures) { + irBuiltIns.knownBuiltins.forEach { it.acceptVoid(mangleChecker) } + } return IrModuleInfo(moduleFragment, deserializedModuleFragments, irBuiltIns, symbolTable, irLinker, moduleFragmentToUniqueName) } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.kt index 6b4a83fd5cb..5797891695f 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/KotlinMultiFileTestWithJava.kt @@ -19,7 +19,6 @@ import org.jetbrains.kotlin.test.TestFiles import org.jetbrains.kotlin.test.TestFiles.TestFileFactory import org.jetbrains.kotlin.test.util.KtTestUtil import java.io.File -import java.util.* abstract class KotlinMultiFileTestWithJava : KotlinBaseTest() { @@ -140,7 +139,7 @@ abstract class KotlinMultiFileTestWithJava, friends: List): M? { + override fun createModule(name: String, dependencies: List, friends: List, abiVersions: List): M? { val module = createTestModule(name, dependencies, friends) val oldValue = modules.put(name, ModuleAndDependencies(module, dependencies, friends)) assert(oldValue == null) { "Module $name declared more than once" } diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/compatibility/binary/AbstractKlibBinaryCompatibilityTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/compatibility/binary/AbstractKlibBinaryCompatibilityTest.kt index 3a7df264152..d177f52c68d 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/compatibility/binary/AbstractKlibBinaryCompatibilityTest.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/compatibility/binary/AbstractKlibBinaryCompatibilityTest.kt @@ -64,7 +64,7 @@ abstract class AbstractKlibBinaryCompatibilityTest : KotlinTestWithEnvironment() TestFile(module, fileName, text, directives) } ?: error("Expected a module for $fileName in $filePath") - override fun createModule(name: String, dependencies: List, friends: List) = + override fun createModule(name: String, dependencies: List, friends: List, abiVersions: List) = TestModule(name, dependencies, friends) }, diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/TestFiles.java b/compiler/tests-common/tests/org/jetbrains/kotlin/test/TestFiles.java index ae54d7ef45a..2b48c7e012e 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/TestFiles.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/TestFiles.java @@ -10,10 +10,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.TestHelperGeneratorKt; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -33,7 +30,7 @@ public class TestFiles { */ private static final String MODULE_DELIMITER = ",\\s*"; - private static final Pattern MODULE_PATTERN = Pattern.compile("//\\s*MODULE:\\s*([^()\\n]+)(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\n"); + private static final Pattern MODULE_PATTERN = Pattern.compile("//\\s*MODULE:\\s*([^()\\n]+)(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*(?:\\(([^()]+(?:" + MODULE_DELIMITER + "[^()]+)*)\\))?\\s*(?:\\((\\d+(?:" + MODULE_DELIMITER + "\\d+)*)\\))?\n"); private static final Pattern FILE_PATTERN = Pattern.compile("//\\s*FILE:\\s*(.*)\n"); private static final Pattern LINE_SEPARATOR_PATTERN = Pattern.compile("\\r\\n|\\r|\\n"); @@ -88,10 +85,11 @@ public class TestFiles { String moduleName = moduleMatcher.group(1); String moduleDependencies = moduleMatcher.group(2); String moduleFriends = moduleMatcher.group(3); + String abiVersions = moduleMatcher.group(4); if (moduleName != null) { moduleName = moduleName.trim(); hasModules = true; - module = factory.createModule(moduleName, parseModuleList(moduleDependencies), parseModuleList(moduleFriends)); + module = factory.createModule(moduleName, parseModuleList(moduleDependencies), parseModuleList(moduleFriends), parseAbiVersionsList(abiVersions)); M oldValue = modules.put(moduleName, module); assert oldValue == null : "Module with name " + moduleName + " already present in file"; } @@ -138,7 +136,7 @@ public class TestFiles { } if (isDirectiveDefined(expectedText, "WITH_COROUTINES")) { - M supportModule = hasModules ? factory.createModule("support", Collections.emptyList(), Collections.emptyList()) : null; + M supportModule = hasModules ? factory.createModule("support", Collections.emptyList(), Collections.emptyList(), Collections.emptyList()) : null; if (supportModule != null) { M oldValue = modules.put(supportModule.name, supportModule); assert oldValue == null : "Module with name " + supportModule.name + " already present in file"; @@ -201,9 +199,19 @@ public class TestFiles { return kotlin.text.StringsKt.split(dependencies, Pattern.compile(MODULE_DELIMITER), 0); } + private static List parseAbiVersionsList(@Nullable String versions) { + if (versions == null) return Collections.emptyList(); + List splitted = kotlin.text.StringsKt.split(versions, Pattern.compile(MODULE_DELIMITER), 0); + List result = new ArrayList<>(splitted.size()); + for (String s : splitted) { + result.add(Integer.parseInt(s)); + } + return result; + } + public interface TestFileFactory { F createFile(@Nullable M module, @NotNull String fileName, @NotNull String text, @NotNull Directives directives); - M createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends); + M createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends, @NotNull List abiVersions); } public static abstract class TestFileFactoryNoModules implements TestFileFactory { @@ -221,7 +229,7 @@ public class TestFiles { public abstract F create(@NotNull String fileName, @NotNull String text, @NotNull Directives directives); @Override - public KotlinBaseTest.TestModule createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends) { + public KotlinBaseTest.TestModule createModule(@NotNull String name, @NotNull List dependencies, @NotNull List friends, @NotNull List abiVersions) { return null; } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsLineNumberTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsLineNumberTest.kt index c250598584f..d2c93ed8c98 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsLineNumberTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/AbstractJsLineNumberTest.kt @@ -152,7 +152,7 @@ abstract class AbstractJsLineNumberTest : KotlinTestWithEnvironment() { return TestFile(temporaryFile.absolutePath, text, currentModule, directives) } - override fun createModule(name: String, dependencies: List, friends: List) = TestModule(name, dependencies, friends) + override fun createModule(name: String, dependencies: List, friends: List, abiVersion: List) = TestModule(name, dependencies, friends) override fun close() { FileUtil.delete(tmpDir) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ApiTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/ApiTest.kt index e71852652e4..18ee5fedbe7 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ApiTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ApiTest.kt @@ -86,6 +86,7 @@ class ApiTest : KotlinTestWithEnvironment() { resolvedLibraries, listOf(), IrFactoryImpl, + verifySignatures = true ).module.descriptor.packagesSerialized() } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt index 9e3823f3306..f310fc18cdf 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt @@ -46,6 +46,7 @@ import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilderConsumer import org.jetbrains.kotlin.js.test.utils.* import org.jetbrains.kotlin.js.util.TextOutputImpl +import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.metadata.DebugProtoBuf import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction @@ -150,6 +151,7 @@ abstract class BasicBoxTest( val skipDceDriven = SKIP_DCE_DRIVEN.matcher(fileContent).find() val splitPerModule = SPLIT_PER_MODULE.matcher(fileContent).find() + val skipMangleVerification = SKIP_MANGLE_VERIFICATION.matcher(fileContent).find() val propertyLazyInitialization = PROPERTY_LAZY_INITIALIZATION.matcher(fileContent).find() val safeExternalBoolean = SAFE_EXTERNAL_BOOLEAN.matcher(fileContent).find() @@ -197,6 +199,7 @@ abstract class BasicBoxTest( val outputFileName = module.outputFileName(outputDir) + ".js" val dceOutputFileName = module.outputFileName(dceOutputDir) + ".js" val pirOutputFileName = module.outputFileName(pirOutputDir) + ".js" + val abiVersion = module.abiVersion val isMainModule = mainModuleName == module.name logger.logFile("Output JS", File(outputFileName)) @@ -226,6 +229,8 @@ abstract class BasicBoxTest( propertyLazyInitialization, safeExternalBoolean, safeExternalBooleanDiagnostic, + skipMangleVerification, + abiVersion ) when { @@ -481,6 +486,8 @@ abstract class BasicBoxTest( propertyLazyInitialization: Boolean, safeExternalBoolean: Boolean, safeExternalBooleanDiagnostic: RuntimeDiagnostic?, + skipMangleVerification: Boolean, + abiVersion: KotlinAbiVersion ) { val kotlinFiles = module.files.filter { it.fileName.endsWith(".kt") } val testFiles = kotlinFiles.map { it.fileName } @@ -533,6 +540,8 @@ abstract class BasicBoxTest( propertyLazyInitialization, safeExternalBoolean, safeExternalBooleanDiagnostic, + skipMangleVerification, + abiVersion ) if (incrementalCompilationChecksEnabled && module.hasFilesToRecompile) { @@ -629,6 +638,8 @@ abstract class BasicBoxTest( propertyLazyInitialization = false, safeExternalBoolean = false, safeExternalBooleanDiagnostic = null, + skipMangleVerification = false, + abiVersion = KotlinAbiVersion.CURRENT ) val originalOutput = FileUtil.loadFile(outputFile) @@ -710,6 +721,8 @@ abstract class BasicBoxTest( propertyLazyInitialization: Boolean, safeExternalBoolean: Boolean, safeExternalBooleanDiagnostic: RuntimeDiagnostic?, + skipMangleVerification: Boolean, + abiVersion: KotlinAbiVersion ) { val translator = K2JSTranslator(config, false) val translationResult = translator.translateUnits(ExceptionThrowingReporter, units, mainCallParameters) @@ -973,7 +986,7 @@ abstract class BasicBoxTest( private inner class TestFileFactoryImpl() : TestFiles.TestFileFactory, Closeable { var testPackage: String? = null val tmpDir = KtTestUtil.tmpDir("js-tests") - val defaultModule = TestModule(TEST_MODULE, emptyList(), emptyList()) + val defaultModule = TestModule(TEST_MODULE, emptyList(), emptyList(), KotlinAbiVersion.CURRENT) var languageVersionSettings: LanguageVersionSettings? = null override fun createFile(module: TestModule?, fileName: String, text: String, directives: Directives): TestFile? { @@ -1036,8 +1049,13 @@ abstract class BasicBoxTest( ) } - override fun createModule(name: String, dependencies: List, friends: List) = - TestModule(name, dependencies, friends) + override fun createModule(name: String, dependencies: List, friends: List, abiVersions: List): TestModule { + val abiVersion = if (abiVersions.isEmpty()) KotlinAbiVersion.CURRENT else { + assert(abiVersions.size == 3) + KotlinAbiVersion(abiVersions[0], abiVersions[1], abiVersions[2]) + } + return TestModule(name, dependencies, friends, abiVersion) + } override fun close() { FileUtil.delete(tmpDir) @@ -1053,7 +1071,8 @@ abstract class BasicBoxTest( private class TestModule( name: String, dependencies: List, - friends: List + friends: List, + val abiVersion: KotlinAbiVersion ) : KotlinBaseTest.TestModule(name, dependencies, friends) { var moduleKind = ModuleKind.PLAIN var inliningDisabled = false @@ -1108,6 +1127,7 @@ abstract class BasicBoxTest( private val EXPECT_ACTUAL_LINKER = Pattern.compile("^// EXPECT_ACTUAL_LINKER *$", Pattern.MULTILINE) private val SKIP_DCE_DRIVEN = Pattern.compile("^// *SKIP_DCE_DRIVEN *$", Pattern.MULTILINE) private val SPLIT_PER_MODULE = Pattern.compile("^// *SPLIT_PER_MODULE *$", Pattern.MULTILINE) + private val SKIP_MANGLE_VERIFICATION = Pattern.compile("^// *SKIP_MANGLE_VERIFICATION *$", Pattern.MULTILINE) private val ERROR_POLICY_PATTERN = Pattern.compile("^// *ERROR_POLICY: *(.+)$", Pattern.MULTILINE) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt index 6d4d9811f7b..2244221750f 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicIrBoxTest.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.config.RuntimeDiagnostic import org.jetbrains.kotlin.js.facade.MainCallParameters import org.jetbrains.kotlin.js.facade.TranslationUnit +import org.jetbrains.kotlin.library.KotlinAbiVersion import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.parsing.parseBoolean import org.jetbrains.kotlin.test.TargetBackend @@ -98,6 +99,8 @@ abstract class BasicIrBoxTest( propertyLazyInitialization: Boolean, safeExternalBoolean: Boolean, safeExternalBooleanDiagnostic: RuntimeDiagnostic?, + skipMangleVerification: Boolean, + abiVersion: KotlinAbiVersion ) { val filesToCompile = units.map { (it as TranslationUnit.SourceFile).file } @@ -156,6 +159,7 @@ abstract class BasicIrBoxTest( lowerPerModule = lowerPerModule, safeExternalBoolean = safeExternalBoolean, safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic, + verifySignatures = !skipMangleVerification ) compiledModule.jsCode!!.writeTo(outputFile, config) @@ -187,6 +191,7 @@ abstract class BasicIrBoxTest( propertyLazyInitialization = propertyLazyInitialization, safeExternalBoolean = safeExternalBoolean, safeExternalBooleanDiagnostic = safeExternalBooleanDiagnostic, + verifySignatures = !skipMangleVerification ).jsCode!!.writeTo(pirOutputFile, config) } } else { @@ -200,6 +205,8 @@ abstract class BasicIrBoxTest( irFactory = IrFactoryImpl, outputKlibPath = actualOutputFile, nopack = true, + verifySignatures = !skipMangleVerification, + abiVersion = abiVersion, null )