[JS SCRIPTING] create tests for repl
This commit is contained in:
committed by
romanart
parent
62885ba497
commit
c6c3d2de9e
@@ -0,0 +1,32 @@
|
|||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
}
|
||||||
|
|
||||||
|
jvmTarget = "1.6"
|
||||||
|
|
||||||
|
val embeddableTestRuntime by configurations.creating
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
testCompile(commonDep("junit"))
|
||||||
|
|
||||||
|
testCompile(project(":kotlin-scripting-js"))
|
||||||
|
testCompile(project(":compiler:plugin-api"))
|
||||||
|
testCompile(project(":kotlin-scripting-compiler"))
|
||||||
|
testCompile(project(":compiler:cli"))
|
||||||
|
testCompile(project(":compiler:backend.js"))
|
||||||
|
testCompile(project(":js:js.engines"))
|
||||||
|
testCompile(intellijCoreDep()) { includeJars("intellij-core") }
|
||||||
|
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||||
|
testRuntimeOnly(intellijDep()) { includeJars("openapi", "idea", "idea_rt", "log4j", "picocontainer-1.2", "guava-25.1-jre", "jdom") }
|
||||||
|
testRuntimeOnly(commonDep("org.jetbrains.intellij.deps", "trove4j"))
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
"main" {}
|
||||||
|
"test" { projectDefault() }
|
||||||
|
}
|
||||||
|
|
||||||
|
projectTest(parallel = true) {
|
||||||
|
workingDir = rootDir
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.repl.js.test
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Disposer
|
||||||
|
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCodeLine
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompiler
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
|
||||||
|
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
|
||||||
|
import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar
|
||||||
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
|
import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar
|
||||||
|
import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.scripting.definitions.platform
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.JsReplEvaluator
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.ReplMessageCollector
|
||||||
|
import java.io.Closeable
|
||||||
|
import kotlin.script.experimental.api.ScriptCompilationConfiguration
|
||||||
|
import kotlin.script.experimental.api.baseClass
|
||||||
|
import kotlin.script.experimental.api.dependencies
|
||||||
|
import kotlin.script.experimental.host.ScriptingHostConfiguration
|
||||||
|
import kotlin.script.experimental.jvm.JsDependency
|
||||||
|
|
||||||
|
abstract class AbstractJsReplTest : Closeable {
|
||||||
|
abstract fun createCompiler(): ReplCompiler
|
||||||
|
abstract fun preprocessEvaluation()
|
||||||
|
|
||||||
|
fun compile(codeLine: ReplCodeLine): ReplCompileResult {
|
||||||
|
return compiler.compile(compiler.createState(), codeLine)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun evaluate(compileResult: ReplCompileResult.CompiledClasses): ReplEvalResult {
|
||||||
|
return jsEvaluator.eval(jsEvaluator.createState(), compileResult)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reset() {
|
||||||
|
collector.clear()
|
||||||
|
compiler = createCompiler()
|
||||||
|
jsEvaluator = JsReplEvaluator()
|
||||||
|
preprocessEvaluation()
|
||||||
|
}
|
||||||
|
|
||||||
|
private val collector: MessageCollector = ReplMessageCollector()
|
||||||
|
protected val disposable = Disposer.newDisposable()
|
||||||
|
protected val environment = KotlinCoreEnvironment.createForProduction(
|
||||||
|
disposable, loadConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES
|
||||||
|
)
|
||||||
|
|
||||||
|
lateinit var compiler: ReplCompiler
|
||||||
|
lateinit var jsEvaluator: JsReplEvaluator
|
||||||
|
|
||||||
|
private var snippetId: Int = 1 //index 0 for klib
|
||||||
|
fun newSnippetId(): Int = snippetId++
|
||||||
|
|
||||||
|
private fun loadConfiguration(): CompilerConfiguration {
|
||||||
|
val configuration = CompilerConfiguration()
|
||||||
|
configuration.add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ScriptingCompilerConfigurationComponentRegistrar())
|
||||||
|
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, collector)
|
||||||
|
configuration.put(CommonConfigurationKeys.MODULE_NAME, "repl.kts")
|
||||||
|
val scriptConfiguration = ScriptCompilationConfiguration {
|
||||||
|
baseClass("kotlin.Any")
|
||||||
|
dependencies.append(JsDependency("compiler/ir/serialization.js/build/fullRuntime/klib"))
|
||||||
|
platform.put("JS")
|
||||||
|
}
|
||||||
|
configuration.add(
|
||||||
|
ScriptingConfigurationKeys.SCRIPT_DEFINITIONS,
|
||||||
|
ScriptDefinition.FromConfigurations(ScriptingHostConfiguration(), scriptConfiguration, null)
|
||||||
|
)
|
||||||
|
return configuration
|
||||||
|
}
|
||||||
|
}
|
||||||
+44
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.repl.js.test
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompiler
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.NameTables
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.*
|
||||||
|
|
||||||
|
class JsReplTestAgainstBinaries : AbstractJsReplTest() {
|
||||||
|
private val dependencyLoader = DependencyLoader()
|
||||||
|
|
||||||
|
private val runtimeBinary: String
|
||||||
|
private val nameTable: NameTables
|
||||||
|
|
||||||
|
init {
|
||||||
|
val dependencies = readLibrariesFromConfiguration(environment.configuration)
|
||||||
|
val compiler = ScriptDependencyCompiler(environment)
|
||||||
|
|
||||||
|
val result = compiler.compile(dependencies)
|
||||||
|
runtimeBinary = result.first
|
||||||
|
nameTable = result.second
|
||||||
|
|
||||||
|
dependencyLoader.saveScriptDependencyBinary(runtimeBinary)
|
||||||
|
dependencyLoader.saveNames(nameTable)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createCompiler(): ReplCompiler {
|
||||||
|
return JsDebuggerCompiler(environment, dependencyLoader.loadNames())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun preprocessEvaluation() {
|
||||||
|
jsEvaluator.eval(
|
||||||
|
jsEvaluator.createState(),
|
||||||
|
createCompileResult(dependencyLoader.loadScriptDependencyBinary())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
//do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
+27
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.repl.js.test
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Disposer
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompiler
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.*
|
||||||
|
|
||||||
|
class JsReplTestAgainstKlib : AbstractJsReplTest() {
|
||||||
|
override fun createCompiler(): ReplCompiler = JsReplCompiler(environment)
|
||||||
|
|
||||||
|
override fun preprocessEvaluation() {
|
||||||
|
val scriptDependencyBinary = (compiler as JsReplCompiler).scriptDependencyBinary
|
||||||
|
|
||||||
|
jsEvaluator.eval(
|
||||||
|
jsEvaluator.createState(),
|
||||||
|
createCompileResult(scriptDependencyBinary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
Disposer.dispose(disposable)
|
||||||
|
}
|
||||||
|
}
|
||||||
+243
@@ -0,0 +1,243 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 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.scripting.repl.js.test
|
||||||
|
|
||||||
|
import junit.framework.TestCase
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Test
|
||||||
|
import org.jetbrains.kotlin.cli.common.repl.ReplEvalResult
|
||||||
|
import org.jetbrains.kotlin.scripting.repl.js.makeReplCodeLine
|
||||||
|
|
||||||
|
abstract class AbstractReplTestRunner : TestCase() {
|
||||||
|
abstract fun getTester(): AbstractJsReplTest
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIndependentLines() {
|
||||||
|
val lines = listOf(
|
||||||
|
"var x = 38",
|
||||||
|
"var y = 99",
|
||||||
|
"4 + 1"
|
||||||
|
)
|
||||||
|
Assert.assertEquals(5, compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testDependentLines() {
|
||||||
|
val lines = listOf(
|
||||||
|
"var x = 7",
|
||||||
|
"var y = 32",
|
||||||
|
"x + y"
|
||||||
|
)
|
||||||
|
Assert.assertEquals(39, compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testFunctionCall() {
|
||||||
|
val lines = listOf(
|
||||||
|
"var x = 2",
|
||||||
|
"var y = 3",
|
||||||
|
"fun foo(x: Int, unused: Int) = x + y",
|
||||||
|
"foo(x, x) * foo(y, y)"
|
||||||
|
)
|
||||||
|
Assert.assertEquals(30, compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testList() {
|
||||||
|
val lines = listOf(
|
||||||
|
"var a = 4",
|
||||||
|
"var b = 6",
|
||||||
|
"listOf(a, 5, b).last()"
|
||||||
|
)
|
||||||
|
Assert.assertEquals(6, compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMatchingNames() {
|
||||||
|
val lines = listOf(
|
||||||
|
"fun foo(i: Int) = i + 2",
|
||||||
|
"fun foo(s: String) = s",
|
||||||
|
"class C {fun foo(s: String) = s + s}",
|
||||||
|
"foo(\"x\") + foo(2) + C().foo(\"class\")"
|
||||||
|
)
|
||||||
|
Assert.assertEquals("x4classclass", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInline() {
|
||||||
|
val lines = listOf(
|
||||||
|
"inline fun foo(i : Int) = if (i % 2 == 0) {} else i",
|
||||||
|
"""
|
||||||
|
fun box(): String {
|
||||||
|
val a = foo(1)
|
||||||
|
if (a != 1) return "fail1: ${'$'}a"
|
||||||
|
|
||||||
|
val b = foo(2)
|
||||||
|
if (b != Unit) return "fail2: ${'$'}b"
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
},
|
||||||
|
box()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
Assert.assertEquals("OK", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAnonymous() {
|
||||||
|
val lines = listOf(
|
||||||
|
"""
|
||||||
|
inline fun foo(f: () -> String): () -> String {
|
||||||
|
val result = f()
|
||||||
|
return { result }
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"fun bar(f: () -> String) = foo(f)()",
|
||||||
|
"fun box(): String = bar { \"OK\" }",
|
||||||
|
"box()"
|
||||||
|
)
|
||||||
|
Assert.assertEquals("OK", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNoneLocalReturn() {
|
||||||
|
val lines = listOf(
|
||||||
|
"""
|
||||||
|
inline fun f(ignored: () -> Any): Any {
|
||||||
|
return ignored()
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"""
|
||||||
|
fun test(): String {
|
||||||
|
f { return "OK" };
|
||||||
|
return "error"
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
"test()"
|
||||||
|
)
|
||||||
|
Assert.assertEquals("OK", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInstanceOf() {
|
||||||
|
val lines = listOf(
|
||||||
|
"""
|
||||||
|
val list = listOf(1, 2, 3)
|
||||||
|
val f: Boolean = list is List<Int>
|
||||||
|
""",
|
||||||
|
"val s = list is List<Int>",
|
||||||
|
"f.toString() + s.toString()"
|
||||||
|
)
|
||||||
|
Assert.assertEquals("truetrue", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testScopes() {
|
||||||
|
val lines = listOf(
|
||||||
|
"""
|
||||||
|
fun foo(): Int {
|
||||||
|
var t = 2 * 2
|
||||||
|
class A(val value: Int = 5) {
|
||||||
|
fun bar(): Int {
|
||||||
|
var q = 4
|
||||||
|
var w = 1
|
||||||
|
return q + w
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return A().bar() * 2
|
||||||
|
}
|
||||||
|
foo()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
Assert.assertEquals(10, compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testEvaluateFunctionName() {
|
||||||
|
val lines = listOf(
|
||||||
|
"fun evaluateScript() = 5",
|
||||||
|
"fun foo(i: Int) = i + evaluateScript()",
|
||||||
|
"foo(5)"
|
||||||
|
)
|
||||||
|
Assert.assertEquals(10, compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testMemberDeclarations() {
|
||||||
|
val lines = listOf(
|
||||||
|
"""
|
||||||
|
val a = listOf(1, 2, 3, 4, 5)
|
||||||
|
val str = "" + kotlin.math.PI
|
||||||
|
str + a.subList(2, 3).toString() + a.lastIndexOf(4)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
Assert.assertEquals("3.141592653589793[3]3", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInitializeScriptFunction() {
|
||||||
|
val lines = listOf(
|
||||||
|
"""
|
||||||
|
var result = ""
|
||||||
|
|
||||||
|
class Class(val x: Int = 10)
|
||||||
|
result += Class().x
|
||||||
|
|
||||||
|
fun function() = "#$@"
|
||||||
|
result += function()
|
||||||
|
|
||||||
|
val field = 123456
|
||||||
|
result += field
|
||||||
|
|
||||||
|
val sq: (x: Int) -> Int = { x -> x * x }
|
||||||
|
result += "_" + sq(9)
|
||||||
|
|
||||||
|
result += if (sq(5) % 2 == 0) {
|
||||||
|
class I(val x: Int = 100)
|
||||||
|
I().x
|
||||||
|
} else {
|
||||||
|
class I(val x: String = "goo")
|
||||||
|
I().x
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
Assert.assertEquals("10#$@123456_81goo", compileAndEval(lines))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun compileAndEval(lines: List<String>): Any? {
|
||||||
|
var result: Any? = null
|
||||||
|
getTester().use { tester ->
|
||||||
|
tester.reset()
|
||||||
|
|
||||||
|
lines.forEach { line ->
|
||||||
|
val compileResult = tester.compile(makeReplCodeLine(tester.newSnippetId(), line))
|
||||||
|
if (compileResult !is ReplCompileResult.CompiledClasses) return compileResult.toString()
|
||||||
|
|
||||||
|
val evalResult = tester.evaluate(compileResult)
|
||||||
|
if (evalResult !is ReplEvalResult.ValueResult) return evalResult.toString()
|
||||||
|
|
||||||
|
result = evalResult.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReplTestRunnerAgainstKLib : AbstractReplTestRunner() {
|
||||||
|
override fun getTester(): AbstractJsReplTest = JsReplTestAgainstKlib()
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReplTestRunnerAgainstBinaries : AbstractReplTestRunner() {
|
||||||
|
override fun getTester(): AbstractJsReplTest = tester
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val tester = JsReplTestAgainstBinaries()
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -149,6 +149,9 @@ abstract class ScriptDefinition : UserDataHolderBase() {
|
|||||||
?: hostConfiguration[ScriptingHostConfiguration.jvm.baseClassLoader]
|
?: hostConfiguration[ScriptingHostConfiguration.jvm.baseClassLoader]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val platform: String
|
||||||
|
get() = compilationConfiguration[ScriptCompilationConfiguration.platform] ?: super.platform
|
||||||
|
|
||||||
override val baseClassType: KotlinType
|
override val baseClassType: KotlinType
|
||||||
get() = compilationConfiguration[ScriptCompilationConfiguration.baseClass]!!
|
get() = compilationConfiguration[ScriptCompilationConfiguration.baseClass]!!
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user