Files
kotlin-fork/js/js.tests/build.gradle.kts
T
Artem Kobzar d2b64cd481 [K/JS] Generate .js files from .ts if they were not created, because of the incremental flag in tsconfig
The incremental option will prevent creating file if there is an incremental cache from TS compiler even if the file doesn't exist.
The situation could happen if `./gradlew clean` was executed (js file will be removed and ts incremental cache - not)

Merge-request: KT-MR-10229
Merged-by: Artem Kobzar <Artem.Kobzar@jetbrains.com>
2023-06-14 09:26:18 +00:00

470 lines
16 KiB
Kotlin

import com.github.gradle.node.npm.task.NpmTask
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
import org.jetbrains.kotlin.ideaExt.idea
import org.apache.tools.ant.filters.FixCrLfFilter
import java.util.Properties
plugins {
kotlin("jvm")
kotlin("plugin.serialization")
id("jps-compatible")
id("com.github.node-gradle.node") version "3.2.1"
}
val nodeDir = buildDir.resolve("node")
node {
download.set(true)
version.set(nodejsVersion)
nodeProjectDir.set(nodeDir)
}
val antLauncherJar by configurations.creating
val testJsRuntime by configurations.creating {
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_RUNTIME))
attribute(KotlinPlatformType.attribute, KotlinPlatformType.js)
}
}
dependencies {
testApiJUnit5(vintageEngine = true)
testApi(protobufFull())
testApi(projectTests(":compiler:tests-common"))
testApi(projectTests(":compiler:test-infrastructure"))
testApi(projectTests(":compiler:test-infrastructure-utils"))
testApi(projectTests(":compiler:tests-compiler-utils"))
testApi(projectTests(":compiler:tests-common-new"))
testImplementation(projectTests(":compiler:fir:analysis-tests"))
testCompileOnly(project(":compiler:frontend"))
testCompileOnly(project(":compiler:cli"))
testCompileOnly(project(":compiler:cli-js"))
testCompileOnly(project(":compiler:util"))
testCompileOnly(intellijCore())
testApi(project(":compiler:backend.js"))
testApi(project(":js:js.translator"))
testApi(project(":js:js.serializer"))
testApi(project(":js:js.dce"))
testApi(project(":js:js.engines"))
testApi(project(":compiler:incremental-compilation-impl"))
testApi(commonDependency("junit:junit"))
testApi(projectTests(":kotlin-build-common"))
testApi(projectTests(":generators:test-generator"))
testApi(intellijCore())
testApi(project(":compiler:frontend"))
testApi(project(":compiler:cli"))
testApi(project(":compiler:util"))
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps:trove4j"))
testRuntimeOnly(commonDependency("com.google.guava:guava"))
testRuntimeOnly(commonDependency("org.jetbrains.intellij.deps:jdom"))
testRuntimeOnly(kotlinStdlib())
testJsRuntime(kotlinStdlib("js"))
if (!kotlinBuildProperties.isInJpsBuildIdeaSync) {
testJsRuntime(project(":kotlin-test:kotlin-test-js")) // to be sure that kotlin-test-js built before tests runned
}
testRuntimeOnly(project(":kotlin-preloader")) // it's required for ant tests
testRuntimeOnly(project(":compiler:backend-common"))
testRuntimeOnly(commonDependency("org.fusesource.jansi", "jansi"))
antLauncherJar(commonDependency("org.apache.ant", "ant"))
antLauncherJar(toolsJar())
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:${commonDependencyVersion("org.junit", "junit-bom")}")
testImplementation(commonDependency("org.jetbrains.kotlinx", "kotlinx-serialization-json"))
testImplementation(commonDependency("io.ktor", "ktor-client-core"))
testImplementation(commonDependency("io.ktor", "ktor-client-cio"))
testImplementation(commonDependency("io.ktor", "ktor-client-websockets"))
}
val generationRoot = projectDir.resolve("tests-gen")
useD8Plugin()
optInToExperimentalCompilerApi()
sourceSets {
"main" { }
"test" {
projectDefault()
this.java.srcDir(generationRoot.name)
}
}
if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
apply(plugin = "idea")
idea {
this.module.generatedSourceDirs.add(generationRoot)
}
}
abstract class MochaTestTask : NpmTask(), VerificationTask
val testDataDir = project(":js:js.translator").projectDir.resolve("testData")
val typescriptTestsDir = testDataDir.resolve("typescript-export")
val installTsDependencies = task<NpmTask>("installTsDependencies") {
val packageLockFile = testDataDir.resolve("package-lock.json")
inputs.file(testDataDir.resolve("package.json"))
outputs.file(packageLockFile)
outputs.upToDateWhen { packageLockFile.exists() }
workingDir.set(testDataDir)
args.set(listOf("install"))
}
fun parallel(tasksToRun: List<Task>, beforeAll: Task? = null, afterAll: Task? = null) = tasks.registering {
tasksToRun.forEach { dependsOn(it) }
if (beforeAll != null) {
tasksToRun.forEach { it.dependsOn(beforeAll) }
}
if (afterAll != null) {
finalizedBy(afterAll)
}
}
val exportFileDirPostfix = "-in-exported-file"
fun generateJsExportOnFileTestFor(dir: String): Task = task<Copy>("generate-js-export-on-file-for-$dir") {
val dirPostfix = exportFileDirPostfix
val inputDir = fileTree(typescriptTestsDir.resolve(dir))
val outputDir = typescriptTestsDir.resolve("$dir$dirPostfix")
inputs.files(inputDir.matching {
include("**/*.kt")
include("**/*.ts")
include("**/tsconfig.json")
})
outputs.dir(outputDir)
from(inputDir) {
include("**/*.kt")
include("**/*.ts")
include("**/tsconfig.json")
}
eachFile {
var isFirstLine = true
filter {
when {
isFirstLine && name.endsWith(".kt") -> "/** This file is generated by {@link :js:js.test:generateJsExportOnFileTestFilesForTS} task. DO NOT MODIFY MANUALLY */\n\n$it"
.also { isFirstLine = false }
it.contains("// FILE") -> "$it\n\n@file:JsExport"
else -> it.replace("@JsExport(?!.)".toRegex(), "")
}
}
filter(
FixCrLfFilter::class,
"eol" to FixCrLfFilter.CrLf.newInstance("lf"),
"fixlast" to false
)
}
into(outputDir)
}
fun generateTypeScriptTestFor(dir: String): Task = task<NpmTask>("generate-ts-for-$dir") {
val baseDir = typescriptTestsDir.resolve(dir)
val mainTsFile = fileTree(baseDir).files.find { it.name.endsWith("__main.ts") } ?: return@task
val mainJsFile = baseDir.resolve("${mainTsFile.nameWithoutExtension}.js")
workingDir.set(testDataDir)
inputs.file(mainTsFile)
outputs.file(mainJsFile)
outputs.upToDateWhen { mainJsFile.exists() }
args.set(listOf("run", "generateTypeScriptTests", "--", "./typescript-export/$dir/tsconfig.json"))
}
val generateTypeScriptTests by parallel(
beforeAll = installTsDependencies,
tasksToRun = typescriptTestsDir.listFiles { it: File ->
it.isDirectory &&
!it.path.endsWith("module-systems") &&
!it.path.endsWith("module-systems-in-exported-file")
}
.map { generateTypeScriptTestFor(it.name) }
)
val generateTypeScriptJsExportOnFileTests by parallel(
typescriptTestsDir
.listFiles { it: File ->
it.isDirectory &&
!it.path.endsWith("selective-export") &&
!it.path.endsWith("implicit-export") &&
!it.path.endsWith("inheritance") &&
!it.path.endsWith("strict-implicit-export") &&
!it.path.endsWith("private-primary-constructor") &&
!it.path.endsWith(exportFileDirPostfix)
}
.map { generateJsExportOnFileTestFor(it.name) }
)
fun Test.setupNodeJs() {
systemProperty("javascript.engine.path.NodeJs", com.github.gradle.node.variant.VariantComputer()
.let { variantComputer ->
variantComputer
.computeNodeDir(node)
.let { variantComputer.computeNodeBinDir(it) }
.let { variantComputer.computeNodeExec(node, it) }
.get()
}
)
}
fun Test.setUpJsBoxTests(jsEnabled: Boolean, jsIrEnabled: Boolean, firEnabled: Boolean, es6Enabled: Boolean) {
setupV8()
if (jsIrEnabled) {
setupNodeJs()
dependsOn(npmInstall)
}
inputs.files(rootDir.resolve("js/js.engines/src/org/jetbrains/kotlin/js/engine/repl.js"))
dependsOn(":dist")
dependsOn(generateTypeScriptTests)
if (jsEnabled) {
dependsOn(testJsRuntime)
inputs.files(testJsRuntime)
}
if (jsIrEnabled) {
dependsOn(":kotlin-stdlib-js-ir:compileKotlinJs")
systemProperty("kotlin.js.full.stdlib.path", "libraries/stdlib/js-ir/build/classes/kotlin/js/main")
inputs.dir(rootDir.resolve("libraries/stdlib/js-ir/build/classes/kotlin/js/main"))
systemProperty("kotlin.js.stdlib.klib.path", "libraries/stdlib/js-ir/build/libs/kotlin-stdlib-js-ir-js-$version.klib")
inputs.file(rootDir.resolve("libraries/stdlib/js-ir/build/libs/kotlin-stdlib-js-ir-js-$version.klib"))
dependsOn(":kotlin-stdlib-js-ir-minimal-for-test:compileKotlinJs")
systemProperty("kotlin.js.reduced.stdlib.path", "libraries/stdlib/js-ir-minimal-for-test/build/classes/kotlin/js/main")
inputs.dir(rootDir.resolve("libraries/stdlib/js-ir-minimal-for-test/build/classes/kotlin/js/main"))
dependsOn(":kotlin-test:kotlin-test-js-ir:compileKotlinJs")
systemProperty("kotlin.js.kotlin.test.path", "libraries/kotlin.test/js-ir/build/classes/kotlin/js/main")
inputs.dir(rootDir.resolve("libraries/kotlin.test/js-ir/build/classes/kotlin/js/main"))
}
exclude("org/jetbrains/kotlin/js/testOld/api/*")
if (jsEnabled && !jsIrEnabled) {
include("org/jetbrains/kotlin/integration/AntTaskJsTest.class")
include("org/jetbrains/kotlin/js/testOld/*")
include("org/jetbrains/kotlin/js/testOld/ast/*")
include("org/jetbrains/kotlin/js/testOld/optimizer/*")
include("org/jetbrains/kotlin/js/test/*")
}
if (!jsEnabled) {
when {
firEnabled -> {
include("org/jetbrains/kotlin/js/test/fir/*")
}
es6Enabled -> {
include("org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.class")
include("org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.class")
include("org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenInlineTestGenerated.class")
include("org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxErrorTestGenerated.class")
include("org/jetbrains/kotlin/incremental/JsIrES6InvalidationTestGenerated.class")
}
else -> {
include("org/jetbrains/kotlin/js/test/ir/*")
include("org/jetbrains/kotlin/incremental/*")
include("org/jetbrains/kotlin/js/testOld/compatibility/binary/JsKlibBinaryCompatibilityTestGenerated.class")
include("org/jetbrains/kotlin/benchmarks/GenerateIrRuntime.class")
include("org/jetbrains/kotlin/integration/JsIrAnalysisHandlerExtensionTest.class")
exclude("org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.class")
exclude("org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.class")
exclude("org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenInlineTestGenerated.class")
exclude("org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxErrorTestGenerated.class")
exclude("org/jetbrains/kotlin/incremental/JsIrES6InvalidationTestGenerated.class")
}
}
}
jvmArgs("-da:jdk.nashorn.internal.runtime.RecompilableScriptFunctionData") // Disable assertion which fails due to a bug in nashorn (KT-23637)
setUpBoxTests()
}
fun Test.forwardProperties() {
val rootLocalProperties = Properties().apply {
rootProject.file("local.properties").takeIf { it.isFile }?.inputStream()?.use {
load(it)
}
}
val allProperties = properties + rootLocalProperties
val prefixForPropertiesToForward = "fd."
for ((key, value) in allProperties) {
if (key is String && key.startsWith(prefixForPropertiesToForward)) {
systemProperty(key.substring(prefixForPropertiesToForward.length), value!!)
}
}
}
fun Test.setUpBoxTests() {
workingDir = rootDir
dependsOn(antLauncherJar)
inputs.files(antLauncherJar)
val antLauncherJarPath = antLauncherJar.asPath
doFirst {
systemProperty("kotlin.ant.classpath", antLauncherJarPath)
systemProperty("kotlin.ant.launcher.class", "org.apache.tools.ant.Main")
}
systemProperty("kotlin.js.test.root.out.dir", "$nodeDir/")
systemProperty(
"overwrite.output", project.providers.gradleProperty("overwrite.output")
.forUseAtConfigurationTime().orNull ?: "false"
)
forwardProperties()
}
val test = projectTest(jUnitMode = JUnitMode.JUnit5) {
setUpJsBoxTests(jsEnabled = true, jsIrEnabled = true, firEnabled = true, es6Enabled = true)
inputs.dir(rootDir.resolve("compiler/cli/cli-common/resources")) // compiler.xml
inputs.dir(testDataDir)
inputs.dir(rootDir.resolve("dist"))
inputs.dir(rootDir.resolve("compiler/testData"))
outputs.dir("$buildDir/out")
outputs.dir("$buildDir/out-min")
configureTestDistribution()
}
val jsTest = projectTest("jsTest", jUnitMode = JUnitMode.JUnit5) {
setUpJsBoxTests(jsEnabled = true, jsIrEnabled = false, firEnabled = false, es6Enabled = false)
useJUnitPlatform()
}
projectTest("jsIrTest", jUnitMode = JUnitMode.JUnit5) {
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true, firEnabled = false, es6Enabled = false)
useJUnitPlatform()
}
projectTest("jsIrES6Test", jUnitMode = JUnitMode.JUnit5) {
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true, firEnabled = false, es6Enabled = true)
useJUnitPlatform()
}
projectTest("jsFirTest", jUnitMode = JUnitMode.JUnit5) {
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true, firEnabled = true, es6Enabled = false)
useJUnitPlatform()
}
projectTest("quickTest", jUnitMode = JUnitMode.JUnit5) {
setUpJsBoxTests(jsEnabled = true, jsIrEnabled = false, firEnabled = false, es6Enabled = false)
systemProperty("kotlin.js.skipMinificationTest", "true")
useJUnitPlatform()
}
projectTest("jsStdlibApiTest", parallel = true, maxHeapSizeMb = 4096) {
setupV8()
setupNodeJs()
dependsOn(npmInstall)
dependsOn(":dist")
inputs.dir(rootDir.resolve("dist"))
include("org/jetbrains/kotlin/js/testOld/api/*")
inputs.dir(rootDir.resolve("libraries/stdlib/api/js"))
inputs.dir(rootDir.resolve("libraries/stdlib/api/js-v1"))
dependsOn(":kotlin-stdlib-js-ir:compileKotlinJs")
systemProperty("kotlin.js.full.stdlib.path", "libraries/stdlib/js-ir/build/classes/kotlin/js/main")
inputs.dir(rootDir.resolve("libraries/stdlib/js-ir/build/classes/kotlin/js/main"))
setTestNameIncludePatterns(listOf("org.jetbrains.kotlin.js.testOld.api.ApiTest.*"))
setUpBoxTests()
}
testsJar {}
val generateTests by generator("org.jetbrains.kotlin.generators.tests.GenerateJsTestsKt") {
dependsOn(":compiler:generateTestData")
dependsOn(generateTypeScriptJsExportOnFileTests)
}
val testJsFile = testDataDir.resolve("test.js")
val packageJsonFile = testDataDir.resolve("package.json")
val prepareNpmTestData by task<Copy> {
inputs.files(testJsFile, packageJsonFile)
outputs.dir(nodeDir)
from(testJsFile)
from(packageJsonFile)
into(nodeDir)
}
val npmInstall by tasks.getting(NpmTask::class) {
val packageLockFile = testDataDir.resolve("package-lock.json")
inputs.file(nodeDir.resolve("package.json"))
outputs.file(packageLockFile)
outputs.upToDateWhen { packageLockFile.exists() }
workingDir.set(nodeDir)
dependsOn(prepareNpmTestData)
}
val mochaTest by task<MochaTestTask> {
workingDir.set(nodeDir)
val target = if (project.hasProperty("teamcity")) "runOnTeamcity" else "test"
args.set(listOf("run", target))
ignoreExitValue.set(kotlinBuildProperties.ignoreTestFailures)
dependsOn(npmInstall)
environment.set(
mapOf(
"KOTLIN_JS_LOCATION" to rootDir.resolve("dist/js/kotlin.js").toString(),
"KOTLIN_JS_TEST_LOCATION" to rootDir.resolve("dist/js/kotlin-test.js").toString(),
"BOX_FLAG_LOCATION" to rootDir.resolve("compiler/testData/jsBoxFlag.js").toString()
)
)
}
val runMocha by tasks.registering {
dependsOn(jsTest)
finalizedBy(mochaTest)
}
projectTest("invalidationTest", jUnitMode = JUnitMode.JUnit5) {
workingDir = rootDir
useJsIrBoxTests(version = version, buildDir = "$buildDir/")
include("org/jetbrains/kotlin/incremental/*")
dependsOn(":dist")
forwardProperties()
useJUnitPlatform()
}
tasks.named("check") {
dependsOn(runMocha)
}