From 319440718c28b22ebba35c6d877283252dbfda0c Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 21 Mar 2017 13:30:04 +0100 Subject: [PATCH] Add more JSR 223 and repl tests, fix double aggregation of GenericRepl state - repl test with compilation error - JSR 223 compilable tests --- .../kotlin/cli/jvm/repl/GenericRepl.kt | 2 +- .../kotlin/cli/jvm/repl/GenericReplTest.kt | 165 ++++++++++-------- .../jsr223/KotlinJsr223ScriptEngineIT.kt | 40 ++++- 3 files changed, 126 insertions(+), 81 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt index 60947de0977..66f2df6bfae 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/jvm/repl/GenericRepl.kt @@ -38,7 +38,7 @@ open class GenericRepl protected constructor( protected val compiler: ReplCompiler by lazy { GenericReplCompiler(disposable, scriptDefinition, compilerConfiguration, messageCollector) } 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) diff --git a/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt b/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt index 12954a06130..ca3a098ea59 100644 --- a/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt +++ b/compiler/tests/org/jetbrains/kotlin/cli/jvm/repl/GenericReplTest.kt @@ -30,117 +30,116 @@ import org.jetbrains.kotlin.script.KotlinScriptDefinitionFromAnnotatedTemplate import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.TestJdkKind +import org.jetbrains.kotlin.util.KotlinFrontEndException import org.junit.Test +import java.io.Closeable import java.io.File import java.net.URLClassLoader import java.util.concurrent.locks.ReentrantReadWriteLock class GenericReplTest : TestCase() { + @Test 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, - listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), - "kotlin.script.templates.standard.ScriptTemplateWithArgs") + val codeLine0 = ReplCodeLine(0, 0, "val l1 = listOf(1 + 2)\nl1.first()") + val res2 = repl.replCompiler.compile(state, codeLine0) + 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 =")) - TestCase.assertTrue("Unexpected check results: $res1", res1 is ReplCheckResult.Incomplete) + val codeLine1 = ReplCodeLine(1, 0, "val x = 5") + 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 res2 = repl.replCompiler.compile(state, codeLine0) - val res2c = res2 as? ReplCompileResult.CompiledClasses - TestCase.assertNotNull("Unexpected compile result: $res2", res2c) + val res31 = repl.compiledEvaluator.eval(state, res3c!!) + val res31e = res31 as? ReplEvalResult.UnitResult + TestCase.assertNotNull("Unexpected eval result: $res31", res31e) - 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 codeLine2 = ReplCodeLine(2, 0, "x + 2") + val res4 = repl.replCompiler.compile(state, codeLine2) + val res4c = res4 as? ReplCompileResult.CompiledClasses + TestCase.assertNotNull("Unexpected compile result: $res4", res4c) - val codeLine1 = ReplCodeLine(1, 0, "val x = 5") - val res3 = repl.replCompiler.compile(state, codeLine1) - val res3c = res3 as? ReplCompileResult.CompiledClasses - TestCase.assertNotNull("Unexpected compile result: $res3", res3c) + val res41 = repl.compiledEvaluator.eval(state, res4c!!) + val res41e = res41 as? ReplEvalResult.ValueResult + TestCase.assertNotNull("Unexpected eval result: $res41", res41e) + TestCase.assertEquals(7, res41e!!.value) + } + } - val res31 = repl.compiledEvaluator.eval(state, res3c!!) - val res31e = res31 as? ReplEvalResult.UnitResult - TestCase.assertNotNull("Unexpected eval result: $res31", res31e) + @Test + fun testReplErrors() { + TestRepl().use { repl -> + val state = repl.createState() + repl.compileAndEval(state, ReplCodeLine(0, 0, "val x = 10")) - val codeLine2 = ReplCodeLine(2, 0, "x + 2") - val res4 = repl.replCompiler.compile(state, codeLine2) - val res4c = res4 as? ReplCompileResult.CompiledClasses - TestCase.assertNotNull("Unexpected compile result: $res4", res4c) + val res = repl.compileAndEval(state, ReplCodeLine(1, 0, "java.util.fish")) + TestCase.assertTrue("Expected compile error", res.first is ReplCompileResult.Error) - val res41 = repl.compiledEvaluator.eval(state, res4c!!) - val res41e = res41 as? ReplEvalResult.ValueResult - TestCase.assertNotNull("Unexpected eval result: $res41", res41e) - TestCase.assertEquals(7, res41e!!.value) - - Disposer.dispose(disposable) + val result = repl.compileAndEval(state, ReplCodeLine(2, 0, "x")) + assertEquals(10, (result.second as ReplEvalResult.ValueResult).value) + } } @Test fun testReplCodeFormat() { + TestRepl().use { repl -> + val state = repl.createState() - val disposable = Disposer.newDisposable() - - val repl = TestRepl(disposable, - listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), - "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) + 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) + } } @Test 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, - listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), - "kotlin.script.templates.standard.ScriptTemplateWithArgs") + 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 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 res1 = repl.replCompiler.compile(state, codeLine1) - val res1c = res1 as? ReplCompileResult.CompiledClasses - TestCase.assertNotNull("Unexpected compile result: $res1", res1c) - - 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) + 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) + } } } + internal class TestRepl( - disposable: Disposable, - templateClasspath: List, - templateClassName: String -) { + templateClasspath: List = listOf(File(KotlinIntegrationTestBase.getCompilerLib(), "kotlin-runtime.jar")), + templateClassName: String = "kotlin.script.templates.standard.ScriptTemplateWithArgs" +) : Closeable { + + private val disposable: Disposable by lazy { Disposer.newDisposable() } + val emptyScriptArgs = ScriptArgsWithTypes(arrayOf(emptyArray()), arrayOf(Array::class)) 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<*> = AggregatedReplStageState(replCompiler.createState(lock), compiledEvaluator.createState(lock), lock) + + override fun close() { + Disposer.dispose(disposable) + } } +private fun TestRepl.compileAndEval(state: IReplStageState<*>, codeLine: ReplCodeLine): Pair { + + val compRes = replCompiler.compile(state, codeLine) + + val evalRes = (compRes as? ReplCompileResult.CompiledClasses)?.let { + + compiledEvaluator.eval(state, it) + } + return compRes to evalRes +} diff --git a/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt b/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt index 9cb2d11b16a..ba63f38666a 100644 --- a/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt +++ b/libraries/examples/kotlin-jsr223-local-example/src/test/kotlin/org/jetbrains/kotlin/script/jsr223/KotlinJsr223ScriptEngineIT.kt @@ -22,10 +22,7 @@ import org.junit.Assert import org.junit.Test import java.lang.management.ManagementFactory import java.util.concurrent.TimeUnit -import javax.script.Invocable -import javax.script.ScriptEngine -import javax.script.ScriptEngineManager -import javax.script.SimpleBindings +import javax.script.* class KotlinJsr223LocalScriptEngineIT { @@ -96,6 +93,41 @@ obj 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 fun testEvalWithContext() { val engine = ScriptEngineManager().getEngineByExtension("kts")!!