Add more JSR 223 and repl tests, fix double aggregation of GenericRepl state

- repl test with compilation error
- JSR 223 compilable tests
This commit is contained in:
Ilya Chernikov
2017-03-21 13:30:04 +01:00
parent adc541c3b1
commit 319440718c
3 changed files with 126 additions and 81 deletions
@@ -38,7 +38,7 @@ open class GenericRepl protected constructor(
protected val compiler: ReplCompiler by lazy { GenericReplCompiler(disposable, scriptDefinition, compilerConfiguration, messageCollector) } protected val compiler: ReplCompiler by lazy { GenericReplCompiler(disposable, scriptDefinition, compilerConfiguration, messageCollector) }
protected val evaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(compiler, compilerConfiguration.jvmClasspathRoots, baseClassloader, fallbackScriptArgs, repeatingMode) } protected val evaluator: ReplFullEvaluator by lazy { GenericReplCompilingEvaluator(compiler, compilerConfiguration.jvmClasspathRoots, baseClassloader, fallbackScriptArgs, repeatingMode) }
override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = AggregatedReplStageState(compiler.createState(lock), evaluator.createState(lock), lock) override fun createState(lock: ReentrantReadWriteLock): IReplStageState<*> = evaluator.createState(lock)
override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult = compiler.check(state, codeLine) override fun check(state: IReplStageState<*>, codeLine: ReplCodeLine): ReplCheckResult = compiler.check(state, codeLine)
@@ -30,117 +30,116 @@ import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate
import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.util.KotlinFrontEndException
import org.junit.Test import org.junit.Test
import java.io.Closeable
import java.io.File import java.io.File
import java.net.URLClassLoader import java.net.URLClassLoader
import java.util.concurrent.locks.ReentrantReadWriteLock import java.util.concurrent.locks.ReentrantReadWriteLock
class GenericReplTest : TestCase() { class GenericReplTest : TestCase() {
@Test @Test
fun testReplBasics() { fun testReplBasics() {
TestRepl().use { repl ->
val state = repl.createState()
val disposable = Disposer.newDisposable() val res1 = repl.replCompiler.check(state, ReplCodeLine(0, 0, "val x ="))
TestCase.assertTrue("Unexpected check results: $res1", res1 is ReplCheckResult.Incomplete)
val repl = TestRepl(disposable, val codeLine0 = ReplCodeLine(0, 0, "val l1 = listOf(1 + 2)\nl1.first()")
listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), val res2 = repl.replCompiler.compile(state, codeLine0)
"kotlin.script.templates.standard.ScriptTemplateWithArgs") val res2c = res2 as? ReplCompileResult.CompiledClasses
TestCase.assertNotNull("Unexpected compile result: $res2", res2c)
val state = repl.createState() val res21 = repl.compiledEvaluator.eval(state, res2c!!)
val res21e = res21 as? ReplEvalResult.ValueResult
TestCase.assertNotNull("Unexpected eval result: $res21", res21e)
TestCase.assertEquals(3, res21e!!.value)
val res1 = repl.replCompiler.check(state, ReplCodeLine(0, 0, "val x =")) val codeLine1 = ReplCodeLine(1, 0, "val x = 5")
TestCase.assertTrue("Unexpected check results: $res1", res1 is ReplCheckResult.Incomplete) val res3 = repl.replCompiler.compile(state, codeLine1)
val res3c = res3 as? ReplCompileResult.CompiledClasses
TestCase.assertNotNull("Unexpected compile result: $res3", res3c)
val codeLine0 = ReplCodeLine(0, 0, "val l1 = listOf(1 + 2)\nl1.first()") val res31 = repl.compiledEvaluator.eval(state, res3c!!)
val res2 = repl.replCompiler.compile(state, codeLine0) val res31e = res31 as? ReplEvalResult.UnitResult
val res2c = res2 as? ReplCompileResult.CompiledClasses TestCase.assertNotNull("Unexpected eval result: $res31", res31e)
TestCase.assertNotNull("Unexpected compile result: $res2", res2c)
val res21 = repl.compiledEvaluator.eval(state, res2c!!) val codeLine2 = ReplCodeLine(2, 0, "x + 2")
val res21e = res21 as? ReplEvalResult.ValueResult val res4 = repl.replCompiler.compile(state, codeLine2)
TestCase.assertNotNull("Unexpected eval result: $res21", res21e) val res4c = res4 as? ReplCompileResult.CompiledClasses
TestCase.assertEquals(3, res21e!!.value) TestCase.assertNotNull("Unexpected compile result: $res4", res4c)
val codeLine1 = ReplCodeLine(1, 0, "val x = 5") val res41 = repl.compiledEvaluator.eval(state, res4c!!)
val res3 = repl.replCompiler.compile(state, codeLine1) val res41e = res41 as? ReplEvalResult.ValueResult
val res3c = res3 as? ReplCompileResult.CompiledClasses TestCase.assertNotNull("Unexpected eval result: $res41", res41e)
TestCase.assertNotNull("Unexpected compile result: $res3", res3c) TestCase.assertEquals(7, res41e!!.value)
}
}
val res31 = repl.compiledEvaluator.eval(state, res3c!!) @Test
val res31e = res31 as? ReplEvalResult.UnitResult fun testReplErrors() {
TestCase.assertNotNull("Unexpected eval result: $res31", res31e) TestRepl().use { repl ->
val state = repl.createState()
repl.compileAndEval(state, ReplCodeLine(0, 0, "val x = 10"))
val codeLine2 = ReplCodeLine(2, 0, "x + 2") val res = repl.compileAndEval(state, ReplCodeLine(1, 0, "java.util.fish"))
val res4 = repl.replCompiler.compile(state, codeLine2) TestCase.assertTrue("Expected compile error", res.first is ReplCompileResult.Error)
val res4c = res4 as? ReplCompileResult.CompiledClasses
TestCase.assertNotNull("Unexpected compile result: $res4", res4c)
val res41 = repl.compiledEvaluator.eval(state, res4c!!) val result = repl.compileAndEval(state, ReplCodeLine(2, 0, "x"))
val res41e = res41 as? ReplEvalResult.ValueResult assertEquals(10, (result.second as ReplEvalResult.ValueResult).value)
TestCase.assertNotNull("Unexpected eval result: $res41", res41e) }
TestCase.assertEquals(7, res41e!!.value)
Disposer.dispose(disposable)
} }
@Test @Test
fun testReplCodeFormat() { fun testReplCodeFormat() {
TestRepl().use { repl ->
val state = repl.createState()
val disposable = Disposer.newDisposable() val codeLine0 = ReplCodeLine(0, 0, "val l1 = 1\r\nl1\r\n")
val res0 = repl.replCompiler?.check(state, codeLine0)
val repl = TestRepl(disposable, val res0c = res0 as? ReplCheckResult.Ok
listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), TestCase.assertNotNull("Unexpected compile result: $res0", res0c)
"kotlin.script.templates.standard.ScriptTemplateWithArgs") }
val state = repl.createState()
val codeLine0 = ReplCodeLine(0, 0, "val l1 = 1\r\nl1\r\n")
val res0 = repl.replCompiler?.check(state, codeLine0)
val res0c = res0 as? ReplCheckResult.Ok
TestCase.assertNotNull("Unexpected compile result: $res0", res0c)
Disposer.dispose(disposable)
} }
@Test @Test
fun testRepPackage() { fun testRepPackage() {
TestRepl().use { repl ->
val state = repl.createState()
val disposable = Disposer.newDisposable() val codeLine1 = ReplCodeLine(0, 0, "package mypackage\n\nval x = 1\nx+2")
val res1 = repl.replCompiler.compile(state, codeLine1)
val res1c = res1 as? ReplCompileResult.CompiledClasses
TestCase.assertNotNull("Unexpected compile result: $res1", res1c)
val repl = TestRepl(disposable, val res11 = repl.compiledEvaluator.eval(state, res1c!!)
listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), val res11e = res11 as? ReplEvalResult.ValueResult
"kotlin.script.templates.standard.ScriptTemplateWithArgs") TestCase.assertNotNull("Unexpected eval result: $res11", res11e)
TestCase.assertEquals(3, res11e!!.value)
val state = repl.createState() val codeLine2 = ReplCodeLine(1, 0, "x+4")
val res2 = repl.replCompiler.compile(state, codeLine2)
val res2c = res2 as? ReplCompileResult.CompiledClasses
TestCase.assertNotNull("Unexpected compile result: $res2", res2c)
val codeLine1 = ReplCodeLine(0, 0, "package mypackage\n\nval x = 1\nx+2") val res21 = repl.compiledEvaluator.eval(state, res2c!!)
val res1 = repl.replCompiler.compile(state, codeLine1) val res21e = res21 as? ReplEvalResult.ValueResult
val res1c = res1 as? ReplCompileResult.CompiledClasses TestCase.assertNotNull("Unexpected eval result: $res21", res21e)
TestCase.assertNotNull("Unexpected compile result: $res1", res1c) TestCase.assertEquals(5, res21e!!.value)
}
val res11 = repl.compiledEvaluator.eval(state, res1c!!)
val res11e = res11 as? ReplEvalResult.ValueResult
TestCase.assertNotNull("Unexpected eval result: $res11", res11e)
TestCase.assertEquals(3, res11e!!.value)
val codeLine2 = ReplCodeLine(1, 0, "x+4")
val res2 = repl.replCompiler.compile(state, codeLine2)
val res2c = res2 as? ReplCompileResult.CompiledClasses
TestCase.assertNotNull("Unexpected compile result: $res2", res2c)
val res21 = repl.compiledEvaluator.eval(state, res2c!!)
val res21e = res21 as? ReplEvalResult.ValueResult
TestCase.assertNotNull("Unexpected eval result: $res21", res21e)
TestCase.assertEquals(5, res21e!!.value)
Disposer.dispose(disposable)
} }
} }
internal class TestRepl( internal class TestRepl(
disposable: Disposable, templateClasspath: List<File> = listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")),
templateClasspath: List<File>, templateClassName: String = "kotlin.script.templates.standard.ScriptTemplateWithArgs"
templateClassName: String ) : Closeable {
) {
private val disposable: Disposable by lazy { Disposer.newDisposable() }
val emptyScriptArgs = ScriptArgsWithTypes(arrayOf(emptyArray<String>()), arrayOf(Array<String>::class)) val emptyScriptArgs = ScriptArgsWithTypes(arrayOf(emptyArray<String>()), arrayOf(Array<String>::class))
private val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, *templateClasspath.toTypedArray()).apply { private val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK, *templateClasspath.toTypedArray()).apply {
@@ -165,5 +164,19 @@ internal class TestRepl(
fun createState(lock: ReentrantReadWriteLock = ReentrantReadWriteLock()): IReplStageState<*> = fun createState(lock: ReentrantReadWriteLock = ReentrantReadWriteLock()): IReplStageState<*> =
AggregatedReplStageState(replCompiler.createState(lock), compiledEvaluator.createState(lock), lock) AggregatedReplStageState(replCompiler.createState(lock), compiledEvaluator.createState(lock), lock)
override fun close() {
Disposer.dispose(disposable)
}
} }
private fun TestRepl.compileAndEval(state: IReplStageState<*>, codeLine: ReplCodeLine): Pair<ReplCompileResult, ReplEvalResult?> {
val compRes = replCompiler.compile(state, codeLine)
val evalRes = (compRes as? ReplCompileResult.CompiledClasses)?.let {
compiledEvaluator.eval(state, it)
}
return compRes to evalRes
}
@@ -22,10 +22,7 @@ import org.junit.Assert
import org.junit.Test import org.junit.Test
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import javax.script.Invocable import javax.script.*
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager
import javax.script.SimpleBindings
class KotlinJsr223LocalScriptEngineIT { class KotlinJsr223LocalScriptEngineIT {
@@ -96,6 +93,41 @@ obj
Assert.assertEquals(6, res3) Assert.assertEquals(6, res3)
} }
@Test
fun testSimpleCompilable() {
val engine = ScriptEngineManager().getEngineByExtension("kts") as KotlinJsr223JvmLocalScriptEngine
val comp1 = engine.compile("val x = 3")
val comp2 = engine.compile("x + 2")
val res1 = comp1.eval()
Assert.assertNull(res1)
val res2 = comp2.eval()
Assert.assertEquals(5, res2)
}
@Test
fun testMultipleCompilable() {
val engine = ScriptEngineManager().getEngineByExtension("kts") as KotlinJsr223JvmLocalScriptEngine
val compiled1 = engine.compile("""listOf(1,2,3).joinToString(",")""")
val compiled2 = engine.compile("""val x = bindings["boundValue"] as Int + bindings["z"] as Int""")
val compiled3 = engine.compile("""x""")
Assert.assertEquals("1,2,3", compiled1.eval())
Assert.assertEquals("1,2,3", compiled1.eval())
Assert.assertEquals("1,2,3", compiled1.eval())
Assert.assertEquals("1,2,3", compiled1.eval())
engine.getBindings(ScriptContext.ENGINE_SCOPE).apply {
put("boundValue", 100)
put("z", 33)
}
compiled2.eval()
Assert.assertEquals(133, compiled3.eval())
Assert.assertEquals(133, compiled3.eval())
Assert.assertEquals(133, compiled3.eval())
}
@Test @Test
fun testEvalWithContext() { fun testEvalWithContext() {
val engine = ScriptEngineManager().getEngineByExtension("kts")!! val engine = ScriptEngineManager().getEngineByExtension("kts")!!