Enable K2 scripting tests

This commit is contained in:
Ilya Chernikov
2023-05-03 16:27:30 +02:00
committed by Space Team
parent 266a223460
commit 480ea80fc4
20 changed files with 148 additions and 92 deletions
+1
View File
@@ -718,6 +718,7 @@ tasks {
register("scriptingTest") { register("scriptingTest") {
dependsOn("scriptingJvmTest") dependsOn("scriptingJvmTest")
dependsOn("scriptingK2Test")
} }
register("compilerTest") { register("compilerTest") {
@@ -56,5 +56,5 @@ projectTest(parallel = true) {
projectTest(taskName = "testWithK2", parallel = true) { projectTest(taskName = "testWithK2", parallel = true) {
dependsOn(":dist") dependsOn(":dist")
workingDir = rootDir workingDir = rootDir
systemProperty("kotlin.script.base.compiler.arguments", "-Xuse-k2") systemProperty("kotlin.script.base.compiler.arguments", "-language-version 2.0")
} }
@@ -43,7 +43,7 @@ class CachingTest : TestCase() {
} }
@Test @Test
fun testSimpleImportWithMemoryCache() { fun testSimpleImportWithMemoryCache() = expectTestToFailOnK2 {
val cache = SimpleMemoryScriptsCache() val cache = SimpleMemoryScriptsCache()
checkWithCache( checkWithCache(
cache, scriptWithImport, scriptWithImportExpectedOutput, cache, scriptWithImport, scriptWithImportExpectedOutput,
@@ -63,7 +63,7 @@ class CachingTest : TestCase() {
} }
@Test @Test
fun testSimpleImportWithFileCache() { fun testSimpleImportWithFileCache() = expectTestToFailOnK2 {
withTempDir("scriptingTestCache") { cacheDir -> withTempDir("scriptingTestCache") { cacheDir ->
val cache = FileBasedScriptCache(cacheDir) val cache = FileBasedScriptCache(cacheDir)
Assert.assertEquals(true, cache.baseDir.listFiles()?.isEmpty()) Assert.assertEquals(true, cache.baseDir.listFiles()?.isEmpty())
@@ -90,7 +90,7 @@ class CachingTest : TestCase() {
} }
@Test @Test
fun testSimpleImportWithJarCache() { fun testSimpleImportWithJarCache() = expectTestToFailOnK2 {
withTempDir("scriptingTestJarCache") { cacheDir -> withTempDir("scriptingTestJarCache") { cacheDir ->
val cache = TestCompiledScriptJarsCache(cacheDir) val cache = TestCompiledScriptJarsCache(cacheDir)
Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty()) Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty())
@@ -110,7 +110,7 @@ class CachingTest : TestCase() {
} }
@Test @Test
fun testImplicitReceiversWithJarCache() { fun testImplicitReceiversWithJarCache() = expectTestToFailOnK2 {
withTempDir("scriptingTestJarCache") { cacheDir -> withTempDir("scriptingTestJarCache") { cacheDir ->
val cache = TestCompiledScriptJarsCache(cacheDir) val cache = TestCompiledScriptJarsCache(cacheDir)
Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty()) Assert.assertTrue(cache.baseDir.listFiles()!!.isEmpty())
@@ -181,7 +181,7 @@ class CachingTest : TestCase() {
} }
@Test @Test
fun testLocalDependencyWithExternalLoadAndCache() { fun testLocalDependencyWithExternalLoadAndCache() = expectTestToFailOnK2 {
withTempDir("scriptingTestDepDir") { depDir -> withTempDir("scriptingTestDepDir") { depDir ->
val standardJars = KotlinJars.kotlinScriptStandardJars val standardJars = KotlinJars.kotlinScriptStandardJars
val outJar = makeDependenciesJar(depDir, standardJars) val outJar = makeDependenciesJar(depDir, standardJars)
@@ -13,7 +13,7 @@ import kotlin.test.assertTrue
class CapturingTest { class CapturingTest {
@Test @Test
fun testScriptWithImplicitReceiverAndSimpleCapturing() { fun testScriptWithImplicitReceiverAndSimpleCapturing() = expectTestToFailOnK2 {
// Reproducing (a bit extended) scenario from KT-53947: without the fix, in the presence of the implicit receiver // Reproducing (a bit extended) scenario from KT-53947: without the fix, in the presence of the implicit receiver
// of the same type as the receiver in the `apply` function body, the lowering was incorrectly substituting // of the same type as the receiver in the `apply` function body, the lowering was incorrectly substituting
// the correct receiver with the accessor to the implicit one // the correct receiver with the accessor to the implicit one
@@ -36,7 +36,7 @@ class CapturingTest {
} }
@Test @Test
fun testScriptWithImplicitReceiverAndNoCapturing() { fun testScriptWithImplicitReceiverAndNoCapturing() = expectTestToFailOnK2 {
// Reproducing (a bit extended) scenario from KT-53947: without the fix, in the presence of the implicit receiver // Reproducing (a bit extended) scenario from KT-53947: without the fix, in the presence of the implicit receiver
// of the same type as the receiver in the `C2.apply` function body, the lowering was incorrectly substituting // of the same type as the receiver in the `C2.apply` function body, the lowering was incorrectly substituting
// the correct receiver with the accessor to the implicit one // the correct receiver with the accessor to the implicit one
@@ -22,7 +22,7 @@ import kotlin.script.experimental.jvmhost.createJvmEvaluationConfigurationFromTe
class ConfigurationDslTest : TestCase() { class ConfigurationDslTest : TestCase() {
@Test @Test
fun testComposableRefinementHandlers() { fun testComposableRefinementHandlers() = expectTestToFailOnK2 {
val baseConfig = createJvmCompilationConfigurationFromTemplate<SimpleScript> { val baseConfig = createJvmCompilationConfigurationFromTemplate<SimpleScript> {
updateClasspath(classpathFromClass<SimpleScript>()) updateClasspath(classpathFromClass<SimpleScript>())
defaultImports(MyTestAnnotation1::class, MyTestAnnotation2::class) defaultImports(MyTestAnnotation1::class, MyTestAnnotation2::class)
@@ -24,7 +24,7 @@ class ConstructorArgumentsOrderTest {
} }
@Test @Test
fun testScriptWithImplicitReceiver() { fun testScriptWithImplicitReceiver() = expectTestToFailOnK2 {
val res = evalString<ScriptWithImplicitReceiver>("""println(receiverString)""") { val res = evalString<ScriptWithImplicitReceiver>("""println(receiverString)""") {
implicitReceivers(ImplicitReceiverClass("Hello Receiver!")) implicitReceivers(ImplicitReceiverClass("Hello Receiver!"))
} }
@@ -36,7 +36,7 @@ class ConstructorArgumentsOrderTest {
} }
@Test @Test
fun testScriptWithBoth() { fun testScriptWithBoth() = expectTestToFailOnK2 {
val res = evalString<ScriptWithBoth>("""println(providedString + receiverString)""") { val res = evalString<ScriptWithBoth>("""println(providedString + receiverString)""") {
providedProperties("providedString" to "Hello") providedProperties("providedString" to "Hello")
implicitReceivers(ImplicitReceiverClass(" Both!")) implicitReceivers(ImplicitReceiverClass(" Both!"))
@@ -34,7 +34,8 @@ import kotlin.script.experimental.jvmhost.JvmScriptCompiler
* underlying module will be introduced. * underlying module will be introduced.
*/ */
class ImplicitsFromScriptResultTest : TestCase() { class ImplicitsFromScriptResultTest : TestCase() {
fun testImplicits() {
fun testImplicits() = expectTestToFailOnK2 {
// the implementation of the Compiler Host doesn't work with IR - the inter-script symbol table // the implementation of the Compiler Host doesn't work with IR - the inter-script symbol table
// should be maintained to make it run (see latest REPL compiler implementations for details // should be maintained to make it run (see latest REPL compiler implementations for details
// TODO: consider either fix it or rewrite to the REPL compiler // TODO: consider either fix it or rewrite to the REPL compiler
@@ -41,26 +41,27 @@ class ResolveDependenciesTest : TestCase() {
""".trimMargin() """.trimMargin()
private val funAndValImportScript = funAndValImportScriptText.toScriptSource() private val funAndValImportScript = funAndValImportScriptText.toScriptSource()
// All tests with dependencies from classloader are expected to fail until the KT-60443 is implemented
@Test @Test
fun testResolveClassFromClassloader() { fun testResolveClassFromClassloader() = expectTestToFailOnK2 {
runScriptAndCheckResult(classAccessScript, configurationWithDependenciesFromClassloader, null, 42) runScriptAndCheckResult(classAccessScript, configurationWithDependenciesFromClassloader, null, 42)
runScriptAndCheckResult(classImportScript, configurationWithDependenciesFromClassloader, null, 42) runScriptAndCheckResult(classImportScript, configurationWithDependenciesFromClassloader, null, 42)
} }
@Test @Test
fun testResolveClassFromClasspath() { fun testResolveClassFromClasspath() = expectTestToFailOnK2 {
runScriptAndCheckResult(classAccessScript, configurationWithDependenciesFromClasspath, null, 42) runScriptAndCheckResult(classAccessScript, configurationWithDependenciesFromClasspath, null, 42)
runScriptAndCheckResult(classImportScript, configurationWithDependenciesFromClasspath, null, 42) runScriptAndCheckResult(classImportScript, configurationWithDependenciesFromClasspath, null, 42)
} }
@Test @Test
fun testResolveFunAndValFromClassloader() { fun testResolveFunAndValFromClassloader() = expectTestToFailOnK2 {
runScriptAndCheckResult(funAndValAccessScript, configurationWithDependenciesFromClassloader, null, 42) runScriptAndCheckResult(funAndValAccessScript, configurationWithDependenciesFromClassloader, null, 42)
runScriptAndCheckResult(funAndValImportScript, configurationWithDependenciesFromClassloader, null, 42) runScriptAndCheckResult(funAndValImportScript, configurationWithDependenciesFromClassloader, null, 42)
} }
@Test @Test
fun testReplResolveFunAndValFromClassloader() { fun testReplResolveFunAndValFromClassloader() = expectTestToFailOnK2 {
checkEvaluateInRepl( checkEvaluateInRepl(
sequenceOf(funAndValAccessScriptText, funAndValAccessScriptText), sequenceOf(42, 42), sequenceOf(funAndValAccessScriptText, funAndValAccessScriptText), sequenceOf(42, 42),
configurationWithDependenciesFromClassloader, configurationWithDependenciesFromClassloader,
@@ -75,13 +76,13 @@ class ResolveDependenciesTest : TestCase() {
} }
@Test @Test
fun testResolveFunAndValFromClasspath() { fun testResolveFunAndValFromClasspath() = expectTestToFailOnK2 {
runScriptAndCheckResult(funAndValAccessScript, configurationWithDependenciesFromClasspath, null, 42) runScriptAndCheckResult(funAndValAccessScript, configurationWithDependenciesFromClasspath, null, 42)
runScriptAndCheckResult(funAndValImportScript, configurationWithDependenciesFromClasspath, null, 42) runScriptAndCheckResult(funAndValImportScript, configurationWithDependenciesFromClasspath, null, 42)
} }
@Test @Test
fun testResolveClassFromClassloaderIsolated() { fun testResolveClassFromClassloaderIsolated() = expectTestToFailOnK2 {
val evaluationConfiguration = ScriptEvaluationConfiguration { val evaluationConfiguration = ScriptEvaluationConfiguration {
jvm { jvm {
baseClassLoader(null) baseClassLoader(null)
@@ -91,7 +92,7 @@ class ResolveDependenciesTest : TestCase() {
} }
@Test @Test
fun testResolveClassesFromClassloaderAndClassPath() { fun testResolveClassesFromClassloaderAndClassPath() = expectTestToFailOnK2 {
val script = """ val script = """
org.jetbrains.kotlin.mainKts.MainKtsConfigurator() org.jetbrains.kotlin.mainKts.MainKtsConfigurator()
${thisPackage}.ShouldBeVisibleFromScript().x ${thisPackage}.ShouldBeVisibleFromScript().x
@@ -65,7 +65,7 @@ class ScriptingHostTest : TestCase() {
} }
@Test @Test
fun testValueResult() { fun testValueResult() = expectTestToFailOnK2 {
val evalScriptWithResult = evalScriptWithResult("42") val evalScriptWithResult = evalScriptWithResult("42")
val resVal = evalScriptWithResult as ResultValue.Value val resVal = evalScriptWithResult as ResultValue.Value
Assert.assertEquals(42, resVal.value) Assert.assertEquals(42, resVal.value)
@@ -91,7 +91,7 @@ class ScriptingHostTest : TestCase() {
} }
@Test @Test
fun testCustomResultField() { fun testCustomResultField() = expectTestToFailOnK2 {
val resVal = evalScriptWithResult("42") { val resVal = evalScriptWithResult("42") {
resultField("outcome") resultField("outcome")
} as ResultValue.Value } as ResultValue.Value
@@ -190,7 +190,7 @@ class ScriptingHostTest : TestCase() {
} }
@Test @Test
fun testSimpleImport() { fun testSimpleImport() = expectTestToFailOnK2 {
val greeting = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!") val greeting = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
val script = "println(\"Hello from imported \$helloScriptName script!\")" val script = "println(\"Hello from imported \$helloScriptName script!\")"
val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> { val compilationConfiguration = createJvmCompilationConfigurationFromTemplate<SimpleScriptTemplate> {
@@ -203,7 +203,7 @@ class ScriptingHostTest : TestCase() {
} }
@Test @Test
fun testSimpleImportWithImplicitReceiver() { fun testSimpleImportWithImplicitReceiver() = expectTestToFailOnK2 {
val greeting = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!") val greeting = listOf("Hello from helloWithVal script!", "Hello from imported helloWithVal script!")
val script = "println(\"Hello from imported \$helloScriptName script!\")" val script = "println(\"Hello from imported \$helloScriptName script!\")"
val definition = createJvmScriptDefinitionFromTemplate<SimpleScriptTemplate>( val definition = createJvmScriptDefinitionFromTemplate<SimpleScriptTemplate>(
@@ -224,7 +224,7 @@ class ScriptingHostTest : TestCase() {
} }
@Test @Test
fun testProvidedPropertiesNullability() { fun testProvidedPropertiesNullability() = expectTestToFailOnK2 {
val stringType = KotlinType(String::class) val stringType = KotlinType(String::class)
val definition = createJvmScriptDefinitionFromTemplate<SimpleScriptTemplate>( val definition = createJvmScriptDefinitionFromTemplate<SimpleScriptTemplate>(
compilation = { compilation = {
@@ -273,14 +273,14 @@ class ScriptingHostTest : TestCase() {
} }
@Test @Test
fun testDiamondImportWithoutSharing() { fun testDiamondImportWithoutSharing() = expectTestToFailOnK2 {
val greeting = listOf("Hi from common", "Hi from middle", "Hi from common", "sharedVar == 3") val greeting = listOf("Hi from common", "Hi from middle", "Hi from common", "sharedVar == 3")
val output = doDiamondImportTest() val output = doDiamondImportTest()
Assert.assertEquals(greeting, output) Assert.assertEquals(greeting, output)
} }
@Test @Test
fun testDiamondImportWithSharing() { fun testDiamondImportWithSharing() = expectTestToFailOnK2 {
val greeting = listOf("Hi from common", "Hi from middle", "sharedVar == 5") val greeting = listOf("Hi from common", "Hi from middle", "sharedVar == 5")
val output = doDiamondImportTest( val output = doDiamondImportTest(
ScriptEvaluationConfiguration { ScriptEvaluationConfiguration {
@@ -5,6 +5,7 @@
package kotlin.script.experimental.jvmhost.test package kotlin.script.experimental.jvmhost.test
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.SCRIPT_BASE_COMPILER_ARGUMENTS_PROPERTY
import java.io.File import java.io.File
import java.nio.file.Files import java.nio.file.Files
@@ -19,3 +20,15 @@ internal fun <R> withTempDir(keyName: String = "tmp", body: (File) -> R) {
} }
} }
fun expectTestToFailOnK2(test: () -> Unit) {
val isK2 = System.getProperty(SCRIPT_BASE_COMPILER_ARGUMENTS_PROPERTY)?.contains("-language-version 2.0") == true
var testFailure: Throwable? = null
try {
test()
} catch (e: Throwable) {
testFailure = e
}
if (isK2 && testFailure == null) throw AssertionError("The test is expected to fail on K2")
else if (!isK2 && testFailure != null) throw testFailure
}
@@ -33,7 +33,10 @@ projectTest(parallel = true) {
} }
projectTest(taskName = "testWithK2", parallel = true) { projectTest(taskName = "testWithK2", parallel = true) {
dependsOn(":dist") dependsOn(":dist", ":kotlinx-serialization-compiler-plugin.embeddable:embeddable")
workingDir = rootDir workingDir = rootDir
systemProperty("kotlin.script.base.compiler.arguments", "-Xuse-k2") val localKotlinxSerializationPluginClasspath: FileCollection = kotlinxSerializationGradlePluginClasspath
systemProperty("kotlin.script.test.kotlinx.serialization.plugin.classpath", localKotlinxSerializationPluginClasspath.asPath)
systemProperty("kotlin.script.base.compiler.arguments", "-language-version 2.0")
systemProperty("kotlin.script.test.base.compiler.arguments", "-language-version 2.0")
} }
@@ -7,10 +7,7 @@ package org.jetbrains.kotlin.mainKts.test
import org.jetbrains.kotlin.mainKts.COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR import org.jetbrains.kotlin.mainKts.COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR
import org.jetbrains.kotlin.mainKts.COMPILED_SCRIPTS_CACHE_DIR_PROPERTY import org.jetbrains.kotlin.mainKts.COMPILED_SCRIPTS_CACHE_DIR_PROPERTY
import org.jetbrains.kotlin.scripting.compiler.plugin.runAndCheckResults import org.jetbrains.kotlin.scripting.compiler.plugin.*
import org.jetbrains.kotlin.scripting.compiler.plugin.runWithK2JVMCompiler
import org.jetbrains.kotlin.scripting.compiler.plugin.runWithKotlinLauncherScript
import org.jetbrains.kotlin.scripting.compiler.plugin.runWithKotlinc
import org.jetbrains.kotlin.utils.KotlinPaths import org.jetbrains.kotlin.utils.KotlinPaths
import org.jetbrains.kotlin.utils.PathUtil import org.jetbrains.kotlin.utils.PathUtil
import org.junit.Assert import org.junit.Assert
@@ -69,7 +66,7 @@ class MainKtsIT {
@OptIn(ExperimentalPathApi::class) @OptIn(ExperimentalPathApi::class)
@Test @Test
fun testCache() { fun testCache() = expectTestToFailOnK2 {
val script = File("$TEST_DATA_ROOT/import-test.main.kts").absolutePath val script = File("$TEST_DATA_ROOT/import-test.main.kts").absolutePath
val cache = createTempDirectory("main.kts.test") val cache = createTempDirectory("main.kts.test")
@@ -96,7 +93,7 @@ class MainKtsIT {
@OptIn(ExperimentalPathApi::class) @OptIn(ExperimentalPathApi::class)
@Test @Test
fun testCacheInProcess() { fun testCacheInProcess() = expectTestToFailOnK2 {
val script = File("$TEST_DATA_ROOT/import-test.main.kts").absolutePath val script = File("$TEST_DATA_ROOT/import-test.main.kts").absolutePath
val cache = createTempDirectory("main.kts.test") val cache = createTempDirectory("main.kts.test")
@@ -123,7 +120,7 @@ class MainKtsIT {
@OptIn(ExperimentalPathApi::class) @OptIn(ExperimentalPathApi::class)
@Test @Test
fun testCacheWithFileLocation() { fun testCacheWithFileLocation() = expectTestToFailOnK2 {
val scriptPath = File("$TEST_DATA_ROOT/script-file-location-default.main.kts").absolutePath val scriptPath = File("$TEST_DATA_ROOT/script-file-location-default.main.kts").absolutePath
val cache = createTempDirectory("main.kts.test") val cache = createTempDirectory("main.kts.test")
val expectedTestOutput = listOf(Regex.escape(scriptPath)) val expectedTestOutput = listOf(Regex.escape(scriptPath))
@@ -185,11 +182,13 @@ fun runWithKotlinRunner(
scriptPath: String, scriptPath: String,
expectedOutPatterns: List<String> = emptyList(), expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
cacheDir: Path? = null cacheDir: Path? = null,
expectErrorOnK2: Boolean = false
) { ) {
runWithKotlinLauncherScript( runWithKotlinLauncherScript(
"kotlin", listOf(scriptPath), expectedOutPatterns, expectedExitCode, "kotlin", listOf(scriptPath), expectedOutPatterns, expectedExitCode,
additionalEnvVars = listOf(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR to (cacheDir?.toAbsolutePath()?.toString() ?: "")) additionalEnvVars = listOf(COMPILED_SCRIPTS_CACHE_DIR_ENV_VAR to (cacheDir?.toAbsolutePath()?.toString() ?: "")),
expectErrorOnK2 = expectErrorOnK2
) )
} }
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.mainKts.MainKtsScript
import org.jetbrains.kotlin.mainKts.SCRIPT_FILE_LOCATION_DEFAULT_VARIABLE_NAME import org.jetbrains.kotlin.mainKts.SCRIPT_FILE_LOCATION_DEFAULT_VARIABLE_NAME
import org.jetbrains.kotlin.mainKts.impl.Directories import org.jetbrains.kotlin.mainKts.impl.Directories
import org.jetbrains.kotlin.scripting.compiler.plugin.assertTrue import org.jetbrains.kotlin.scripting.compiler.plugin.assertTrue
import org.jetbrains.kotlin.scripting.compiler.plugin.expectTestToFailOnK2
import org.junit.Assert import org.junit.Assert
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Ignore import org.junit.Ignore
@@ -77,7 +78,7 @@ class MainKtsTest {
} }
@Test @Test
fun testResolveRuntimeDeps() { fun testResolveRuntimeDeps() = expectTestToFailOnK2 {
val resOk = evalFile(File("$TEST_DATA_ROOT/resolve-with-runtime.main.kts")) val resOk = evalFile(File("$TEST_DATA_ROOT/resolve-with-runtime.main.kts"))
assertSucceeded(resOk) assertSucceeded(resOk)
@@ -125,7 +126,7 @@ class MainKtsTest {
} }
@Test @Test
fun testImport() { fun testImport() = expectTestToFailOnK2 {
val out = captureOut { val out = captureOut {
val res = evalFile(File("$TEST_DATA_ROOT/import-test.main.kts")) val res = evalFile(File("$TEST_DATA_ROOT/import-test.main.kts"))
@@ -136,7 +137,7 @@ class MainKtsTest {
} }
@Test @Test
fun testImportWithCapture() { fun testImportWithCapture() = expectTestToFailOnK2 {
val out = captureOut { val out = captureOut {
val res = evalFile(File("$TEST_DATA_ROOT/import-with-capture-test.main.kts")) val res = evalFile(File("$TEST_DATA_ROOT/import-with-capture-test.main.kts"))
@@ -178,7 +179,7 @@ class MainKtsTest {
} }
@Test @Test
fun testScriptFileLocationDefaultVariable() { fun testScriptFileLocationDefaultVariable() = expectTestToFailOnK2 {
val resOk = evalFile(File("$TEST_DATA_ROOT/script-file-location-default.main.kts")) val resOk = evalFile(File("$TEST_DATA_ROOT/script-file-location-default.main.kts"))
assertSucceeded(resOk) assertSucceeded(resOk)
val resultValue = resOk.valueOrThrow().returnValue val resultValue = resOk.valueOrThrow().returnValue
@@ -191,7 +192,7 @@ class MainKtsTest {
} }
@Test @Test
fun testScriptFileLocationCustomizedVariable() { fun testScriptFileLocationCustomizedVariable() = expectTestToFailOnK2 {
val resOk = evalFile(File("$TEST_DATA_ROOT/script-file-location-customized.main.kts")) val resOk = evalFile(File("$TEST_DATA_ROOT/script-file-location-customized.main.kts"))
assertSucceeded(resOk) assertSucceeded(resOk)
val resultValue = resOk.valueOrThrow().returnValue val resultValue = resOk.valueOrThrow().returnValue
@@ -204,7 +205,7 @@ class MainKtsTest {
} }
@Test @Test
fun testScriptFileLocationWithImportedScript() { fun testScriptFileLocationWithImportedScript() = expectTestToFailOnK2 {
val resOk = evalFile(File("$TEST_DATA_ROOT/script-file-location-with-imported-file.main.kts")) val resOk = evalFile(File("$TEST_DATA_ROOT/script-file-location-with-imported-file.main.kts"))
assertSucceeded(resOk) assertSucceeded(resOk)
val resultValue = resOk.valueOrThrow().returnValue val resultValue = resOk.valueOrThrow().returnValue
@@ -69,7 +69,7 @@ projectTest(taskName = "testWithK2", parallel = true) {
dependsOn(":dist") dependsOn(":dist")
workingDir = rootDir workingDir = rootDir
systemProperty("kotlin.test.script.classpath", testSourceSet.output.classesDirs.joinToString(File.pathSeparator)) systemProperty("kotlin.test.script.classpath", testSourceSet.output.classesDirs.joinToString(File.pathSeparator))
systemProperty("kotlin.script.test.base.compiler.arguments", "-Xuse-k2") systemProperty("kotlin.script.test.base.compiler.arguments", "-language-version 2.0")
systemProperty("kotlin.script.base.compiler.arguments", "-Xuse-k2") systemProperty("kotlin.script.base.compiler.arguments", "-language-version 2.0")
} }
@@ -26,12 +26,12 @@ class ScriptingWithCliCompilerTest {
} }
@Test @Test
fun testResultValue() { fun testResultValue() = expectTestToFailOnK2 {
runWithK2JVMCompiler("$TEST_DATA_DIR/integration/intResult.kts", listOf("10")) runWithK2JVMCompiler("$TEST_DATA_DIR/integration/intResult.kts", listOf("10"))
} }
@Test @Test
fun testResultValueViaKotlinc() { fun testResultValueViaKotlinc() = expectTestToFailOnK2 {
runWithKotlinc("$TEST_DATA_DIR/integration/intResult.kts", listOf("10")) runWithKotlinc("$TEST_DATA_DIR/integration/intResult.kts", listOf("10"))
} }
@@ -76,7 +76,7 @@ class ScriptingWithCliCompilerTest {
expectedExitCode = 1, expectedExitCode = 1,
expectedSomeErrPatterns = listOf( expectedSomeErrPatterns = listOf(
"unresolved reference: CompilerOptions" "unresolved reference: CompilerOptions"
) ),
) )
runWithK2JVMCompiler( runWithK2JVMCompiler(
arrayOf( arrayOf(
@@ -132,13 +132,14 @@ class ScriptingWithCliCompilerTest {
} }
@Test @Test
fun testExpressionWithComma() { fun testExpressionWithComma() = expectTestToFailOnK2 {
runWithK2JVMCompiler( runWithK2JVMCompiler(
arrayOf( arrayOf(
"-expression", "-expression",
"listOf(1,2)" "listOf(1,2)"
), ),
listOf("\\[1, 2\\]") listOf("\\[1, 2\\]"),
expectErrorOnK2 = true
) )
} }
@@ -10,6 +10,7 @@ import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.cli.common.CLITool import org.jetbrains.kotlin.cli.common.CLITool
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.SCRIPT_BASE_COMPILER_ARGUMENTS_PROPERTY
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.updateWithCompilerOptions import org.jetbrains.kotlin.scripting.compiler.plugin.impl.updateWithCompilerOptions
import org.junit.Assert import org.junit.Assert
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
@@ -32,11 +33,12 @@ fun runWithKotlinc(
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
workDirectory: File? = null, workDirectory: File? = null,
classpath: List<File> = emptyList(), classpath: List<File> = emptyList(),
additionalEnvVars: Iterable<Pair<String, String>>? = null additionalEnvVars: Iterable<Pair<String, String>>? = null,
expectErrorOnK2: Boolean = false
) { ) {
runWithKotlinc( runWithKotlinc(
arrayOf("-script", scriptPath), arrayOf("-script", scriptPath),
expectedOutPatterns, expectedExitCode, workDirectory, classpath, additionalEnvVars expectedOutPatterns, expectedExitCode, workDirectory, classpath, additionalEnvVars, expectErrorOnK2
) )
} }
@@ -47,7 +49,8 @@ fun runWithKotlinLauncherScript(
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
workDirectory: File? = null, workDirectory: File? = null,
classpath: List<File> = emptyList(), classpath: List<File> = emptyList(),
additionalEnvVars: Iterable<Pair<String, String>>? = null additionalEnvVars: Iterable<Pair<String, String>>? = null,
expectErrorOnK2: Boolean = false
) { ) {
val executableFileName = val executableFileName =
if (System.getProperty("os.name").contains("windows", ignoreCase = true)) "$launcherScriptName.bat" else launcherScriptName if (System.getProperty("os.name").contains("windows", ignoreCase = true)) "$launcherScriptName.bat" else launcherScriptName
@@ -63,7 +66,7 @@ fun runWithKotlinLauncherScript(
addAll(compilerArgs) addAll(compilerArgs)
} }
runAndCheckResults(args, expectedOutPatterns, expectedExitCode, workDirectory, additionalEnvVars) runAndCheckResults(args, expectedOutPatterns, expectedExitCode, workDirectory, additionalEnvVars, expectErrorOnK2 = expectErrorOnK2)
} }
fun runWithKotlinc( fun runWithKotlinc(
@@ -72,10 +75,12 @@ fun runWithKotlinc(
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
workDirectory: File? = null, workDirectory: File? = null,
classpath: List<File> = emptyList(), classpath: List<File> = emptyList(),
additionalEnvVars: Iterable<Pair<String, String>>? = null additionalEnvVars: Iterable<Pair<String, String>>? = null,
expectErrorOnK2: Boolean = false
) { ) {
runWithKotlinLauncherScript( runWithKotlinLauncherScript(
"kotlinc", compilerArgs.asIterable(), expectedOutPatterns, expectedExitCode, workDirectory, classpath, additionalEnvVars "kotlinc", compilerArgs.asIterable(), expectedOutPatterns, expectedExitCode, workDirectory, classpath,
additionalEnvVars, expectErrorOnK2
) )
} }
@@ -84,7 +89,8 @@ fun runAndCheckResults(
expectedOutPatterns: List<String> = emptyList(), expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
workDirectory: File? = null, workDirectory: File? = null,
additionalEnvVars: Iterable<Pair<String, String>>? = null additionalEnvVars: Iterable<Pair<String, String>>? = null,
expectErrorOnK2: Boolean = false
) { ) {
val processBuilder = ProcessBuilder(args) val processBuilder = ProcessBuilder(args)
if (workDirectory != null) { if (workDirectory != null) {
@@ -130,14 +136,22 @@ fun runAndCheckResults(
stderrThread.join(300) stderrThread.join(300)
Assert.assertFalse("stderr thread not finished", stderrThread.isAlive) Assert.assertFalse("stderr thread not finished", stderrThread.isAlive)
Assert.assertNull(stderrException.value) Assert.assertNull(stderrException.value)
Assert.assertEquals(expectedOutPatterns.size, processOut.size)
for ((expectedPattern, actualLine) in expectedOutPatterns.zip(processOut)) { if (expectedExitCode == 0 && expectErrorOnK2 && processOut.contains("Language version 2.0")) {
Assert.assertTrue( Assert.assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"", "Expecting an error on K2 compilation, but got: exit code: ${process.exitValue()}\n$processOut",
Regex(expectedPattern).matches(actualLine) process.exitValue() != 0 || processOut.contains("error: ")
) )
} else {
Assert.assertEquals(expectedOutPatterns.size, processOut.size)
for ((expectedPattern, actualLine) in expectedOutPatterns.zip(processOut)) {
Assert.assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"",
Regex(expectedPattern).matches(actualLine)
)
}
Assert.assertEquals(expectedExitCode, process.exitValue())
} }
Assert.assertEquals(expectedExitCode, process.exitValue())
} catch (e: Throwable) { } catch (e: Throwable) {
println("OUT:\n${processOut.joinToString("\n")}") println("OUT:\n${processOut.joinToString("\n")}")
@@ -150,7 +164,8 @@ fun runWithK2JVMCompiler(
scriptPath: String, scriptPath: String,
expectedOutPatterns: List<String> = emptyList(), expectedOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
classpath: List<File> = emptyList() classpath: List<File> = emptyList(),
expectErrorOnK2: Boolean = false,
) { ) {
val args = arrayListOf("-kotlin-home", "dist/kotlinc").apply { val args = arrayListOf("-kotlin-home", "dist/kotlinc").apply {
if (classpath.isNotEmpty()) { if (classpath.isNotEmpty()) {
@@ -160,14 +175,15 @@ fun runWithK2JVMCompiler(
add("-script") add("-script")
add(scriptPath) add(scriptPath)
} }
runWithK2JVMCompiler(args.toTypedArray(), expectedOutPatterns, expectedExitCode) runWithK2JVMCompiler(args.toTypedArray(), expectedOutPatterns, expectedExitCode, expectErrorOnK2 = expectErrorOnK2)
} }
fun runWithK2JVMCompiler( fun runWithK2JVMCompiler(
args: Array<String>, args: Array<String>,
expectedAllOutPatterns: List<String> = emptyList(), expectedAllOutPatterns: List<String> = emptyList(),
expectedExitCode: Int = 0, expectedExitCode: Int = 0,
expectedSomeErrPatterns: List<String>? = null expectedSomeErrPatterns: List<String>? = null,
expectErrorOnK2: Boolean = false
) { ) {
val argsWithBasefromProp = getBaseCompilerArgumentsFromProperty()?.let { (it + args).toTypedArray() } ?: args val argsWithBasefromProp = getBaseCompilerArgumentsFromProperty()?.let { (it + args).toTypedArray() } ?: args
val (out, err, ret) = captureOutErrRet { val (out, err, ret) = captureOutErrRet {
@@ -178,27 +194,35 @@ fun runWithK2JVMCompiler(
} }
try { try {
val outLines = if (out.isEmpty()) emptyList() else out.lines() val outLines = if (out.isEmpty()) emptyList() else out.lines()
Assert.assertEquals( val errLines by lazy { err.lines() }
"Expecting pattern:\n ${expectedAllOutPatterns.joinToString("\n ")}\nGot:\n ${outLines.joinToString("\n ")}", if (expectErrorOnK2 && errLines.any { it.contains("language version 2.0") }) {
expectedAllOutPatterns.size, outLines.size
)
for ((expectedPattern, actualLine) in expectedAllOutPatterns.zip(outLines)) {
Assert.assertTrue( Assert.assertTrue(
"line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"", "Expecting an error on K2 compilation, but got: exit code: ${ret.code}\n" +
Regex(expectedPattern).matches(actualLine) " ${outLines.joinToString("\n ")}${errLines.joinToString("\n")}",
ret.code != 0 || err.lines().any { it.contains(("error: ")) }
) )
} } else {
if (expectedSomeErrPatterns != null) { Assert.assertEquals(
val errLines = err.lines() "Expecting pattern:\n ${expectedAllOutPatterns.joinToString("\n ")}\nGot:\n ${outLines.joinToString("\n ")}",
for (expectedPattern in expectedSomeErrPatterns) { expectedAllOutPatterns.size, outLines.size
val re = Regex(expectedPattern) )
for ((expectedPattern, actualLine) in expectedAllOutPatterns.zip(outLines)) {
Assert.assertTrue( Assert.assertTrue(
"Expected pattern \"$expectedPattern\" is not found in the stderr:\n${errLines.joinToString("\n")}", "line \"$actualLine\" do not match with expected pattern \"$expectedPattern\"",
errLines.any { re.find(it) != null } Regex(expectedPattern).matches(actualLine)
) )
} }
if (expectedSomeErrPatterns != null) {
for (expectedPattern in expectedSomeErrPatterns) {
val re = Regex(expectedPattern)
Assert.assertTrue(
"Expected pattern \"$expectedPattern\" is not found in the stderr:\n${errLines.joinToString("\n")}",
errLines.any { re.find(it) != null }
)
}
}
Assert.assertEquals(expectedExitCode, ret.code)
} }
Assert.assertEquals(expectedExitCode, ret.code)
} catch (e: Throwable) { } catch (e: Throwable) {
println("OUT:\n$out") println("OUT:\n$out")
println("ERR:\n$err") println("ERR:\n$err")
@@ -258,3 +282,15 @@ fun CompilerConfiguration.updateWithBaseCompilerArguments() {
} }
} }
fun expectTestToFailOnK2(test: () -> Unit) {
val isK2 = System.getProperty(SCRIPT_BASE_COMPILER_ARGUMENTS_PROPERTY)?.contains("-language-version 2.0") == true ||
System.getProperty(SCRIPT_TEST_BASE_COMPILER_ARGUMENTS_PROPERTY)?.contains("-language-version 2.0") == true
var testFailure: Throwable? = null
try {
test()
} catch (e: Throwable) {
testFailure = e
}
if (isK2 && testFailure == null) throw AssertionError("The test is expected to fail on K2")
else if (!isK2 && testFailure != null) throw testFailure
}
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.script.loadScriptingPlugin import org.jetbrains.kotlin.script.loadScriptingPlugin
import org.jetbrains.kotlin.scripting.compiler.plugin.TestDisposable import org.jetbrains.kotlin.scripting.compiler.plugin.TestDisposable
import org.jetbrains.kotlin.scripting.compiler.plugin.expectTestToFailOnK2
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerFromEnvironment import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerFromEnvironment
import org.jetbrains.kotlin.scripting.compiler.plugin.updateWithBaseCompilerArguments import org.jetbrains.kotlin.scripting.compiler.plugin.updateWithBaseCompilerArguments
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
@@ -37,7 +38,7 @@ private const val testDataPath = "plugins/scripting/scripting-compiler/testData/
class CompileTimeFibonacciTest : TestCase() { class CompileTimeFibonacciTest : TestCase() {
private val testRootDisposable: Disposable = TestDisposable() private val testRootDisposable: Disposable = TestDisposable()
fun testFibonacciWithSupportedNumbersImplementsTheCorrectConstants() { fun testFibonacciWithSupportedNumbersImplementsTheCorrectConstants() = expectTestToFailOnK2 {
val outputLines = runScript("supported.fib.kts") val outputLines = runScript("supported.fib.kts")
.valueOr { failure -> .valueOr { failure ->
val message = failure.reports.joinToString("\n") { it.message } val message = failure.reports.joinToString("\n") { it.message }
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.scripting.compiler.test
import junit.framework.TestCase import junit.framework.TestCase
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.scripting.compiler.plugin.expectTestToFailOnK2
import org.jetbrains.kotlin.scripting.compiler.plugin.getBaseCompilerArgumentsFromProperty import org.jetbrains.kotlin.scripting.compiler.plugin.getBaseCompilerArgumentsFromProperty
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated
import org.jetbrains.kotlin.utils.tryConstructClassFromStringArgs import org.jetbrains.kotlin.utils.tryConstructClassFromStringArgs
@@ -85,7 +86,8 @@ class ScriptCompilerTest : TestCase() {
assertEquals("Clazz", nestedClasses[0].simpleName) assertEquals("Clazz", nestedClasses[0].simpleName)
} }
fun testDestructingDeclarations() { // Fails on K2, see KT-60501
fun testDestructingDeclarations() = expectTestToFailOnK2 {
val res = compileToClass( val res = compileToClass(
""" """
val c = 3 val c = 3
@@ -1,15 +1,10 @@
import junit.framework.TestCase import junit.framework.TestCase
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.jetbrains.kotlin.scripting.compiler.plugin.expectTestToFailOnK2
import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated import org.jetbrains.kotlin.scripting.compiler.plugin.impl.ScriptJvmCompilerIsolated
import org.jetbrains.kotlin.scripting.compiler.test.assertEqualsTrimmed import org.jetbrains.kotlin.scripting.compiler.test.assertEqualsTrimmed
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.File
import java.io.InputStream
import java.io.PrintStream import java.io.PrintStream
import java.nio.file.attribute.FileTime
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.util.zip.ZipOutputStream
import kotlin.script.experimental.api.* import kotlin.script.experimental.api.*
import kotlin.script.experimental.host.toScriptSource import kotlin.script.experimental.host.toScriptSource
import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator
@@ -24,7 +19,7 @@ import kotlin.script.experimental.jvm.util.renderError
class ScriptEvaluationTest : TestCase() { class ScriptEvaluationTest : TestCase() {
fun testExceptionWithCause() { fun testExceptionWithCause() = expectTestToFailOnK2 {
checkEvaluateAsError( checkEvaluateAsError(
""" """
try { try {
@@ -43,7 +38,7 @@ class ScriptEvaluationTest : TestCase() {
} }
// KT-19423 // KT-19423
fun testClassCapturingScriptInstance() { fun testClassCapturingScriptInstance() = expectTestToFailOnK2 {
val res = checkEvaluate( val res = checkEvaluate(
""" """
val used = "abc" val used = "abc"
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.script.loadScriptingPlugin import org.jetbrains.kotlin.script.loadScriptingPlugin
import org.jetbrains.kotlin.scripting.compiler.plugin.TestMessageCollector import org.jetbrains.kotlin.scripting.compiler.plugin.TestMessageCollector
import org.jetbrains.kotlin.scripting.compiler.plugin.assertHasMessage import org.jetbrains.kotlin.scripting.compiler.plugin.assertHasMessage
import org.jetbrains.kotlin.scripting.compiler.plugin.expectTestToFailOnK2
import org.jetbrains.kotlin.scripting.compiler.plugin.updateWithBaseCompilerArguments import org.jetbrains.kotlin.scripting.compiler.plugin.updateWithBaseCompilerArguments
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition
@@ -71,7 +72,7 @@ class ScriptTemplateTest : TestCase() {
assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, out) assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, out)
} }
fun testScriptWithBaseClassWithParam() { fun testScriptWithBaseClassWithParam() = expectTestToFailOnK2 {
val messageCollector = TestMessageCollector() val messageCollector = TestMessageCollector()
val aClass = val aClass =
compileScript("fib_dsl.kts", ScriptWithBaseClass::class, null, runIsolated = false, messageCollector = messageCollector) compileScript("fib_dsl.kts", ScriptWithBaseClass::class, null, runIsolated = false, messageCollector = messageCollector)
@@ -119,7 +120,8 @@ class ScriptTemplateTest : TestCase() {
assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, out) assertEqualsTrimmed(NUM_4_LINE + FIB_SCRIPT_OUTPUT_TAIL, out)
} }
fun testScriptWithoutParams() { // Fails on K2, see KT-60452
fun testScriptWithoutParams() = expectTestToFailOnK2 {
val messageCollector = TestMessageCollector() val messageCollector = TestMessageCollector()
val aClass = compileScript("without_params.kts", ScriptWithoutParams::class, null, messageCollector = messageCollector) val aClass = compileScript("without_params.kts", ScriptWithoutParams::class, null, messageCollector = messageCollector)
Assert.assertNotNull("Compilation failed:\n$messageCollector", aClass) Assert.assertNotNull("Compilation failed:\n$messageCollector", aClass)