[Wasm] Add box and stdlib tests in wasi mode
This commit is contained in:
committed by
Zalim Bashorov
parent
f42d0b1ed4
commit
983991d46c
@@ -80,6 +80,10 @@ fun main(args: Array<String>) {
|
||||
testClass<AbstractK1WasmCodegenWasmJsInteropTest> {
|
||||
model("codegen/boxWasmJsInterop")
|
||||
}
|
||||
|
||||
testClass<AbstractK1WasmWasiCodegenBoxTest> {
|
||||
model("codegen/boxWasmWasi")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,11 @@ 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.test.services.EnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfiguratorJs
|
||||
import org.jetbrains.kotlin.wasm.test.converters.FirWasmKlibBackendFacade
|
||||
import org.jetbrains.kotlin.wasm.test.converters.WasmBackendFacade
|
||||
import org.jetbrains.kotlin.wasm.test.handlers.WasmBoxRunner
|
||||
|
||||
|
||||
open class AbstractFirWasmTest(
|
||||
@@ -39,6 +42,12 @@ open class AbstractFirWasmTest(
|
||||
override val afterBackendFacade: Constructor<AbstractTestFacade<BinaryArtifacts.KLib, BinaryArtifacts.Wasm>>
|
||||
get() = ::WasmBackendFacade
|
||||
|
||||
override val wasmBoxTestRunner: Constructor<AnalysisHandler<BinaryArtifacts.Wasm>>
|
||||
get() = ::WasmBoxRunner
|
||||
|
||||
override val wasmEnvironmentConfigurator: Constructor<EnvironmentConfigurator>
|
||||
get() = ::WasmEnvironmentConfiguratorJs
|
||||
|
||||
override fun configure(builder: TestConfigurationBuilder) {
|
||||
super.configure(builder)
|
||||
with(builder) {
|
||||
|
||||
@@ -12,8 +12,11 @@ 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.test.services.EnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfiguratorJs
|
||||
import org.jetbrains.kotlin.wasm.test.converters.FirWasmKlibBackendFacade
|
||||
import org.jetbrains.kotlin.wasm.test.converters.WasmBackendFacade
|
||||
import org.jetbrains.kotlin.wasm.test.handlers.WasmBoxRunner
|
||||
|
||||
abstract class AbstractK1WasmTest(
|
||||
pathToTestDir: String,
|
||||
@@ -32,6 +35,12 @@ abstract class AbstractK1WasmTest(
|
||||
|
||||
override val afterBackendFacade: Constructor<AbstractTestFacade<BinaryArtifacts.KLib, BinaryArtifacts.Wasm>>
|
||||
get() = ::WasmBackendFacade
|
||||
|
||||
override val wasmBoxTestRunner: Constructor<AnalysisHandler<BinaryArtifacts.Wasm>>
|
||||
get() = ::WasmBoxRunner
|
||||
|
||||
override val wasmEnvironmentConfigurator: Constructor<EnvironmentConfigurator>
|
||||
get() = ::WasmEnvironmentConfiguratorJs
|
||||
}
|
||||
|
||||
open class AbstractK1WasmCodegenBoxTest : AbstractK1WasmTest(
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.builders.TestConfigurationBuilder
|
||||
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.test.services.AdditionalSourceProvider
|
||||
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.configuration.WasmEnvironmentConfiguratorWasi
|
||||
import org.jetbrains.kotlin.wasm.test.converters.FirWasmKlibBackendFacade
|
||||
import org.jetbrains.kotlin.wasm.test.converters.WasmBackendFacade
|
||||
import org.jetbrains.kotlin.wasm.test.handlers.WasiBoxRunner
|
||||
|
||||
abstract class AbstractK1WasmWasiTest(
|
||||
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
|
||||
|
||||
override val wasmBoxTestRunner: Constructor<AnalysisHandler<BinaryArtifacts.Wasm>>
|
||||
get() = ::WasiBoxRunner
|
||||
|
||||
override val wasmEnvironmentConfigurator: Constructor<EnvironmentConfigurator>
|
||||
get() = ::WasmEnvironmentConfiguratorWasi
|
||||
|
||||
override val additionalSourceProvider: Constructor<AdditionalSourceProvider>?
|
||||
get() = ::WasmWasiBoxTestHelperSourceProvider
|
||||
}
|
||||
|
||||
open class AbstractK1WasmWasiCodegenBoxTest : AbstractK1WasmWasiTest(
|
||||
"compiler/testData/codegen/boxWasmWasi/",
|
||||
"codegen/k1WasmWasiBox"
|
||||
)
|
||||
+11
-3
@@ -21,10 +21,11 @@ import org.jetbrains.kotlin.test.model.*
|
||||
import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerWithTargetBackendTest
|
||||
import org.jetbrains.kotlin.test.runners.codegen.actualizersAndPluginsFacadeStepIfNeeded
|
||||
import org.jetbrains.kotlin.test.runners.codegen.commonClassicFrontendHandlersForCodegenTest
|
||||
import org.jetbrains.kotlin.test.services.AdditionalSourceProvider
|
||||
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
|
||||
import org.jetbrains.kotlin.test.services.LibraryProvider
|
||||
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>,
|
||||
@@ -36,6 +37,9 @@ abstract class AbstractWasmBlackBoxCodegenTestBase<R : ResultingArtifact.Fronten
|
||||
abstract val frontendToBackendConverter: Constructor<Frontend2BackendConverter<R, I>>
|
||||
abstract val backendFacade: Constructor<BackendFacade<I, A>>
|
||||
abstract val afterBackendFacade: Constructor<AbstractTestFacade<A, BinaryArtifacts.Wasm>>
|
||||
abstract val wasmBoxTestRunner: Constructor<AnalysisHandler<BinaryArtifacts.Wasm>>
|
||||
abstract val wasmEnvironmentConfigurator: Constructor<EnvironmentConfigurator>
|
||||
open val additionalSourceProvider: Constructor<AdditionalSourceProvider>? = null
|
||||
|
||||
override fun TestConfigurationBuilder.configuration() {
|
||||
globalDefaults {
|
||||
@@ -63,7 +67,7 @@ abstract class AbstractWasmBlackBoxCodegenTestBase<R : ResultingArtifact.Fronten
|
||||
}
|
||||
|
||||
useConfigurators(
|
||||
::WasmEnvironmentConfigurator,
|
||||
wasmEnvironmentConfigurator,
|
||||
)
|
||||
|
||||
useAdditionalSourceProviders(
|
||||
@@ -71,6 +75,10 @@ abstract class AbstractWasmBlackBoxCodegenTestBase<R : ResultingArtifact.Fronten
|
||||
::CoroutineHelpersSourceFilesProvider,
|
||||
)
|
||||
|
||||
additionalSourceProvider?.let {
|
||||
useAdditionalSourceProviders(it)
|
||||
}
|
||||
|
||||
useAdditionalService(::LibraryProvider)
|
||||
|
||||
useAfterAnalysisCheckers(
|
||||
@@ -106,7 +114,7 @@ abstract class AbstractWasmBlackBoxCodegenTestBase<R : ResultingArtifact.Fronten
|
||||
}
|
||||
|
||||
wasmArtifactsHandlersStep {
|
||||
useHandlers(::WasmBoxRunner)
|
||||
useHandlers(wasmBoxTestRunner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,13 @@ import org.jetbrains.kotlin.test.services.TestServices
|
||||
import java.io.File
|
||||
import java.io.FileFilter
|
||||
|
||||
class WasmWasiBoxTestHelperSourceProvider(testServices: TestServices) : AdditionalSourceProvider(testServices) {
|
||||
override fun produceAdditionalFiles(globalDirectives: RegisteredDirectives, module: TestModule): List<TestFile> {
|
||||
val boxTestRunFile = File("wasm/wasm.tests/wasiBoxTestRun.kt")
|
||||
return listOf(boxTestRunFile.toTestFile())
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
@@ -24,7 +31,7 @@ class WasmAdditionalSourceProvider(testServices: TestServices) : AdditionalSourc
|
||||
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 const val COMMON_FILES_DIR_PATH = "wasm/wasm.tests/$COMMON_FILES_DIR"
|
||||
|
||||
private fun getFilesInDirectoryByExtension(directory: String, extension: String): List<String> {
|
||||
val dir = File(directory)
|
||||
|
||||
+5
-2
@@ -14,6 +14,8 @@ 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.util.IrMessageLogger
|
||||
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.WasmTarget
|
||||
import org.jetbrains.kotlin.library.KotlinAbiVersion
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.test.backend.ir.IrBackendFacade
|
||||
@@ -52,7 +54,8 @@ class FirWasmKlibBackendFacade(
|
||||
val outputFile = WasmEnvironmentConfigurator.getWasmKlibArtifactPath(testServices, module.name)
|
||||
|
||||
// TODO: consider avoiding repeated libraries resolution
|
||||
val libraries = resolveLibraries(configuration, getAllWasmDependenciesPaths(module, testServices))
|
||||
val target = configuration.get(JSConfigurationKeys.WASM_TARGET, WasmTarget.JS)
|
||||
val libraries = resolveLibraries(configuration, getAllWasmDependenciesPaths(module, testServices, target))
|
||||
|
||||
if (firstTimeCompilation) {
|
||||
serializeModuleIntoKlib(
|
||||
@@ -77,7 +80,7 @@ class FirWasmKlibBackendFacade(
|
||||
|
||||
// TODO: consider avoiding repeated libraries resolution
|
||||
val lib = CommonKLibResolver.resolve(
|
||||
getAllWasmDependenciesPaths(module, testServices) + listOf(outputFile),
|
||||
getAllWasmDependenciesPaths(module, testServices, target) + listOf(outputFile),
|
||||
configuration.resolverLogger
|
||||
).getFullResolvedList().last().library
|
||||
|
||||
|
||||
+10
-2
@@ -20,6 +20,8 @@ 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.js.config.JSConfigurationKeys
|
||||
import org.jetbrains.kotlin.js.config.WasmTarget
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.test.DebugMode
|
||||
@@ -62,9 +64,15 @@ class WasmBackendFacade(
|
||||
PhaseConfig(wasmPhases)
|
||||
}
|
||||
|
||||
val suffix = when (configuration.get(JSConfigurationKeys.WASM_TARGET, WasmTarget.JS)) {
|
||||
WasmTarget.JS -> "-js"
|
||||
WasmTarget.WASI -> "-wasi"
|
||||
else -> error("Unexpected wasi target")
|
||||
}
|
||||
|
||||
val libraries = listOf(
|
||||
System.getProperty("kotlin.wasm.stdlib.path")!!,
|
||||
System.getProperty("kotlin.wasm.kotlin.test.path")!!
|
||||
System.getProperty("kotlin.wasm$suffix.stdlib.path")!!,
|
||||
System.getProperty("kotlin.wasm$suffix.kotlin.test.path")!!
|
||||
) + WasmEnvironmentConfigurator.getAllRecursiveLibrariesFor(module, testServices).map { it.key.libraryFile.canonicalPath }
|
||||
|
||||
val friendLibraries = emptyList<String>()
|
||||
|
||||
+2
-1
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.test.runners.AbstractKotlinCompilerTest
|
||||
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.configuration.WasmEnvironmentConfiguratorJs
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.AdditionalDiagnosticsSourceFilesProvider
|
||||
import org.jetbrains.kotlin.test.services.sourceProviders.CoroutineHelpersSourceFilesProvider
|
||||
|
||||
@@ -37,7 +38,7 @@ abstract class AbstractDiagnosticsWasmTest : AbstractKotlinCompilerTest() {
|
||||
|
||||
useConfigurators(
|
||||
::CommonEnvironmentConfigurator,
|
||||
::WasmEnvironmentConfigurator,
|
||||
::WasmEnvironmentConfiguratorJs,
|
||||
)
|
||||
|
||||
useMetaInfoProcessors(::OldNewInferenceMetaInfoProcessor)
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 WasiBoxRunner(
|
||||
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 originalFile = testServices.moduleStructure.originalTestDataFiles.first()
|
||||
|
||||
val debugMode = DebugMode.fromSystemProperty("kotlin.wasm.debugMode")
|
||||
val startUnitTests = RUN_UNIT_TESTS in testServices.moduleStructure.allDirectives
|
||||
|
||||
val testWasiQuiet = """
|
||||
let boxTestPassed = false;
|
||||
try {
|
||||
let jsModule = await import('./index.mjs');
|
||||
let wasmExports = jsModule.default;
|
||||
${if (startUnitTests) "wasmExports.startUnitTests();" else ""}
|
||||
boxTestPassed = wasmExports.runBoxTest();
|
||||
} catch(e) {
|
||||
console.log('Failed with exception!');
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
if (!boxTestPassed)
|
||||
process.exit(1);
|
||||
""".trimIndent()
|
||||
|
||||
val testWasiVerbose = testWasiQuiet + """
|
||||
|
||||
|
||||
console.log('test passed');
|
||||
""".trimIndent()
|
||||
|
||||
val testWasi = if (debugMode >= DebugMode.DEBUG) testWasiVerbose else testWasiQuiet
|
||||
|
||||
fun writeToFilesAndRunTest(mode: String, res: WasmCompilerResult) {
|
||||
val dir = File(outputDirBase, mode)
|
||||
dir.mkdirs()
|
||||
|
||||
writeCompilationResult(res, dir, baseFileName)
|
||||
File(dir, "test.mjs").writeText(testWasi)
|
||||
|
||||
if (debugMode >= DebugMode.DEBUG) {
|
||||
val path = dir.absolutePath
|
||||
println(" ------ $mode Wat file://$path/index.wat")
|
||||
println(" ------ $mode Wasm file://$path/index.wasm")
|
||||
println(" ------ $mode JS file://$path/index.mjs")
|
||||
println(" ------ $mode Test file://$path/test.mjs")
|
||||
}
|
||||
|
||||
val testFileText = originalFile.readText()
|
||||
val failsIn: List<String> = InTextDirectivesUtils.findListWithPrefixes(testFileText, "// WASM_FAILS_IN: ")
|
||||
|
||||
val exception = WasmVM.NodeJs.runWithCathedExceptions(
|
||||
debugMode = debugMode,
|
||||
disableExceptions = false,
|
||||
failsIn = failsIn,
|
||||
entryMjs = "test.mjs",
|
||||
jsFilePaths = emptyList(),
|
||||
workingDirectory = dir
|
||||
)
|
||||
|
||||
if (exception != null) {
|
||||
throw exception
|
||||
}
|
||||
|
||||
if (mode == "dce") {
|
||||
checkExpectedOutputSize(debugMode, testFileText, dir)
|
||||
}
|
||||
}
|
||||
|
||||
writeToFilesAndRunTest("dev", artifacts.compilerResult)
|
||||
writeToFilesAndRunTest("dce", artifacts.compilerResultWithDCE)
|
||||
}
|
||||
}
|
||||
@@ -92,48 +92,13 @@ class WasmBoxRunner(
|
||||
""".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()
|
||||
@@ -194,26 +159,15 @@ class WasmBoxRunner(
|
||||
|
||||
val disableExceptions = DISABLE_WASM_EXCEPTION_HANDLING in testServices.moduleStructure.allDirectives
|
||||
|
||||
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,
|
||||
disableExceptionHandlingIfPossible = disableExceptions
|
||||
)
|
||||
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
|
||||
val exceptions = listOf(WasmVM.V8, WasmVM.SpiderMonkey).mapNotNull { vm ->
|
||||
vm.runWithCathedExceptions(
|
||||
debugMode = debugMode,
|
||||
disableExceptions = disableExceptions,
|
||||
failsIn = failsIn,
|
||||
entryMjs = entryMjs,
|
||||
jsFilePaths = jsFilePaths,
|
||||
workingDirectory = dir,
|
||||
)
|
||||
}
|
||||
|
||||
when (exceptions.size) {
|
||||
@@ -229,7 +183,7 @@ class WasmBoxRunner(
|
||||
}
|
||||
|
||||
if (mode == "dce") {
|
||||
checkExpectedOutputSize(testFileText, dir)
|
||||
checkExpectedOutputSize(debugMode, testFileText, dir)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,6 +194,35 @@ class WasmBoxRunner(
|
||||
private class AdditionalFile(val name: String, val content: String)
|
||||
}
|
||||
|
||||
internal fun WasmVM.runWithCathedExceptions(
|
||||
debugMode: DebugMode,
|
||||
disableExceptions: Boolean,
|
||||
failsIn: List<String>,
|
||||
entryMjs: String?,
|
||||
jsFilePaths: List<String>,
|
||||
workingDirectory: File,
|
||||
): Throwable? {
|
||||
try {
|
||||
if (debugMode >= DebugMode.DEBUG) {
|
||||
println(" ------ Run in ${name}" + if (shortName in failsIn) " (expected to fail)" else "")
|
||||
}
|
||||
run(
|
||||
"./${entryMjs}",
|
||||
jsFilePaths,
|
||||
workingDirectory = workingDirectory,
|
||||
disableExceptionHandlingIfPossible = disableExceptions,
|
||||
)
|
||||
if (shortName in failsIn) {
|
||||
return AssertionError("The test expected to fail in ${name}. Please update the testdata.")
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
if (shortName !in failsIn) {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun TestServices.getWasmTestOutputDirectory(): File {
|
||||
val originalFile = moduleStructure.originalTestDataFiles.first()
|
||||
val allDirectives = moduleStructure.allDirectives
|
||||
@@ -256,4 +239,41 @@ fun TestServices.getWasmTestOutputDirectory(): File {
|
||||
.toList().asReversed()
|
||||
.fold(testGroupOutputDir, ::File)
|
||||
.let { File(it, originalFile.nameWithoutExtension) }
|
||||
}
|
||||
}
|
||||
|
||||
fun checkExpectedOutputSize(debugMode: DebugMode, 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"))
|
||||
}
|
||||
|
||||
@@ -46,6 +46,17 @@ internal sealed class WasmVM(val shortName: String) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
object NodeJs : WasmVM("NodeJs") {
|
||||
override fun run(entryMjs: String, jsFiles: List<String>, workingDirectory: File?, disableExceptionHandlingIfPossible: Boolean) {
|
||||
tool.run(
|
||||
"--experimental-wasm-gc",
|
||||
*jsFiles.flatMap { listOf("-f", it) }.toTypedArray(),
|
||||
entryMjs,
|
||||
workingDirectory = workingDirectory
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExternalTool(val path: String) {
|
||||
|
||||
Reference in New Issue
Block a user