[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]
|
||||
}
|
||||
|
||||
override val platform: String
|
||||
get() = compilationConfiguration[ScriptCompilationConfiguration.platform] ?: super.platform
|
||||
|
||||
override val baseClassType: KotlinType
|
||||
get() = compilationConfiguration[ScriptCompilationConfiguration.baseClass]!!
|
||||
|
||||
|
||||
Reference in New Issue
Block a user