From 133aea9c4b7b7dfaf83e0f6e0fd955e689c36f70 Mon Sep 17 00:00:00 2001 From: Natalia Ukhorskaya Date: Wed, 9 Apr 2014 14:32:52 +0400 Subject: [PATCH] Debugger: add test for evaluate expression --- .../jet/generators/tests/GenerateTests.kt | 5 + .../debugger/tinyApp/outs/abstractFunCall.out | 7 ++ .../outs/allFilesPresentInEvaluate.out | 0 .../testData/debugger/tinyApp/outs/arrays.out | 7 ++ .../debugger/tinyApp/outs/collections.out | 7 ++ .../testData/debugger/tinyApp/outs/simple.out | 7 ++ .../testData/debugger/tinyApp/outs/stdlib.out | 7 ++ .../tinyApp/src/evaluate/abstractFunCall.kt | 9 ++ .../debugger/tinyApp/src/evaluate/arrays.kt | 33 +++++++ .../tinyApp/src/evaluate/collections.kt | 24 +++++ .../debugger/tinyApp/src/evaluate/simple.kt | 12 +++ .../debugger/tinyApp/src/evaluate/stdlib.kt | 27 +++++ .../AbstractKotlinEvaluateExpressionTest.kt | 99 +++++++++++++++++++ ...KotlinEvaluateExpressionTestGenerated.java | 64 ++++++++++++ 14 files changed, 308 insertions(+) create mode 100644 idea/testData/debugger/tinyApp/outs/abstractFunCall.out create mode 100644 idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out create mode 100644 idea/testData/debugger/tinyApp/outs/arrays.out create mode 100644 idea/testData/debugger/tinyApp/outs/collections.out create mode 100644 idea/testData/debugger/tinyApp/outs/simple.out create mode 100644 idea/testData/debugger/tinyApp/outs/stdlib.out create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/arrays.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/collections.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/simple.kt create mode 100644 idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt create mode 100644 idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt create mode 100644 idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt index 652537ede45..aed89022b7b 100644 --- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt @@ -105,6 +105,7 @@ import org.jetbrains.jet.plugin.codeInsight.AbstractJetInspectionTest import org.jetbrains.jet.plugin.debugger.AbstractKotlinSteppingTest import org.jetbrains.jet.completion.AbstractMultiFileJvmBasicCompletionTest import org.jetbrains.jet.plugin.refactoring.introduce.introduceVariable.AbstractJetExtractionTest +import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressionTest fun main(args: Array) { System.setProperty("java.awt.headless", "true") @@ -557,6 +558,10 @@ fun main(args: Array) { model("debugger/tinyApp/src/stepInto", testMethod = "doSmartStepIntoTest", testClassName = "SmartStepInto") } + testClass(javaClass()) { + model("debugger/tinyApp/src/evaluate") + } + testClass(javaClass()) { model("stubs", extension = "kt") } diff --git a/idea/testData/debugger/tinyApp/outs/abstractFunCall.out b/idea/testData/debugger/tinyApp/outs/abstractFunCall.out new file mode 100644 index 00000000000..4ec5a230c95 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/abstractFunCall.out @@ -0,0 +1,7 @@ +LineBreakpoint created at abstractFunCall.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! abstractFunCall.AbstractFunCallPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +abstractFunCall.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out b/idea/testData/debugger/tinyApp/outs/allFilesPresentInEvaluate.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/debugger/tinyApp/outs/arrays.out b/idea/testData/debugger/tinyApp/outs/arrays.out new file mode 100644 index 00000000000..f523f93f485 --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/arrays.out @@ -0,0 +1,7 @@ +LineBreakpoint created at arrays.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! arrays.ArraysPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +arrays.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/collections.out b/idea/testData/debugger/tinyApp/outs/collections.out new file mode 100644 index 00000000000..f2285270e1b --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/collections.out @@ -0,0 +1,7 @@ +LineBreakpoint created at collections.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! collections.CollectionsPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +collections.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/simple.out b/idea/testData/debugger/tinyApp/outs/simple.out new file mode 100644 index 00000000000..caf68a7723d --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/simple.out @@ -0,0 +1,7 @@ +LineBreakpoint created at simple.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! simple.SimplePackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +simple.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/outs/stdlib.out b/idea/testData/debugger/tinyApp/outs/stdlib.out new file mode 100644 index 00000000000..08dcedff6bc --- /dev/null +++ b/idea/testData/debugger/tinyApp/outs/stdlib.out @@ -0,0 +1,7 @@ +LineBreakpoint created at stdlib.kt:5 +!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !APP_PATH!\classes;!KOTLIN_RUNTIME!;!RT_JAR! stdlib.StdlibPackage +Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' +stdlib.kt:4 +Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket' + +Process finished with exit code 0 diff --git a/idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt b/idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt new file mode 100644 index 00000000000..643597888c1 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt @@ -0,0 +1,9 @@ +package abstractFunCall + +fun main(args: Array) { + //Breakpoint! + args.size +} + +// EXPRESSION: (1 as java.lang.Number).intValue() +// RESULT: 1: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/arrays.kt b/idea/testData/debugger/tinyApp/src/evaluate/arrays.kt new file mode 100644 index 00000000000..2cd229d7f8f --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/arrays.kt @@ -0,0 +1,33 @@ +package arrays + +fun main(args: Array) { + //Breakpoint! + args.size +} + +// EXPRESSION: array(1, 2).map { it.toString() } +// RESULT: instance of java.util.ArrayList(id=347): Ljava/util/ArrayList; + +// EXPRESSION: array(1, 2, 101, 102).filter { it > 100 } +// RESULT: instance of java.util.ArrayList(id=369): Ljava/util/ArrayList; + +// EXPRESSION: array(1, 2).none() +// RESULT: 0: Z + +// EXPRESSION: array(1, 2).count() +// RESULT: 2: I + +// EXPRESSION: array(1, 2).size +// RESULT: 2: I + +// EXPRESSION: array(1, 2).first() +// RESULT: 1: I + +// EXPRESSION: array(1, 2).last() +// RESULT: 2: I + +// EXPRESSION: intArray(1, 2).max() +// RESULT: instance of java.lang.Integer(id=343): Ljava/lang/Integer; + +// EXPRESSION: array(1, 2).max() +// RESULT: instance of java.lang.Integer(id=343): Ljava/lang/Integer; diff --git a/idea/testData/debugger/tinyApp/src/evaluate/collections.kt b/idea/testData/debugger/tinyApp/src/evaluate/collections.kt new file mode 100644 index 00000000000..7abb1c75ce1 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/collections.kt @@ -0,0 +1,24 @@ +package collections + +fun main(args: Array) { + //Breakpoint! + args.size +} + +//// EXPRESSION: arrayListOf(1, 2).map { it.toString() } +//// RESULT: instance of java.util.ArrayList(id=380): Ljava/util/ArrayList; + // +//// EXPRESSION: arrayListOf(1, 2, 101, 102).filter { it > 100 } +//// RESULT: instance of java.util.ArrayList(id=390): Ljava/util/ArrayList; + // +// EXPRESSION: arrayListOf(1, 2).max() +// RESULT: instance of java.lang.Integer(id=343): Ljava/lang/Integer; + // +//// EXPRESSION: arrayListOf(1, 2).count() +//// RESULT: 2: I + // +//// EXPRESSION: arrayListOf(1, 2).size +//// RESULT: 2: I + // +//// EXPRESSION: arrayListOf(1, 2).drop(1) +//// RESULT: instance of java.util.ArrayList(id=411): Ljava/util/ArrayList; diff --git a/idea/testData/debugger/tinyApp/src/evaluate/simple.kt b/idea/testData/debugger/tinyApp/src/evaluate/simple.kt new file mode 100644 index 00000000000..2e472bf30b2 --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/simple.kt @@ -0,0 +1,12 @@ +package simple + +fun main(args: Array) { + //Breakpoint! + args.size +} + +// EXPRESSION: 1 +// RESULT: 1: I + +// EXPRESSION: 1 + 1 +// RESULT: 2: I \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt b/idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt new file mode 100644 index 00000000000..f957ac26eeb --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt @@ -0,0 +1,27 @@ +package stdlib + +fun main(args: Array) { + //Breakpoint! + args.size +} + +// EXPRESSION: array(100, 101) +// RESULT: instance of java.lang.Integer[2] (id=338): [Ljava/lang/Integer; + +// EXPRESSION: array("a", "b", "c") +// RESULT: instance of java.lang.String[3] (id=346): [Ljava/lang/String; + +// EXPRESSION: intArray(1, 2) +// RESULT: instance of int[2] (id=352): [I + +// EXPRESSION: javaClass() +// RESULT: instance of java.lang.Class(reflected class=java.lang.String, id=194): Ljava/lang/Class; + +// EXPRESSION: javaClass() +// RESULT: instance of java.lang.Class(reflected class=int, id=355): Ljava/lang/Class; + +// EXPRESSION: 100.toInt() +// RESULT: 100: I + +// EXPRESSION: 100.toLong() +// RESULT: 100: J \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt new file mode 100644 index 00000000000..d9c952f8332 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/AbstractKotlinEvaluateExpressionTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.debugger.evaluate + +import com.intellij.debugger.DebuggerInvocationUtil +import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilderImpl +import com.intellij.debugger.engine.evaluation.TextWithImportsImpl +import com.intellij.debugger.engine.evaluation.CodeFragmentKind +import com.intellij.debugger.engine.ContextUtil +import com.intellij.debugger.engine.SuspendContextImpl +import org.jetbrains.jet.plugin.debugger.* +import org.junit.Assert +import org.jetbrains.jet.plugin.JetFileType +import com.intellij.openapi.util.io.FileUtil +import java.io.File +import org.jetbrains.jet.InTextDirectivesUtils +import org.jetbrains.eval4j.jdi.asValue + +public abstract class AbstractKotlinEvaluateExpressionTest : KotlinDebuggerTestCase() { + fun doTest(path: String) { + val fileContent = FileUtil.loadFile(File(path)) + val expressions = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, "// EXPRESSION: ") + val expectedResults = InTextDirectivesUtils.findLinesWithPrefixesRemoved(fileContent, "// RESULT: ") + + assert(expressions.size == expectedResults.size, "Sizes of test directives are different") + + createDebugProcess(path) + + onBreakpoint { + val exceptions = arrayListOf() + for ((i, expression) in expressions.withIndices()) { + try { + evaluate(expression, expectedResults[i]) + } + catch (e: Throwable) { + exceptions.add(e) + } + } + + if (exceptions.notEmpty) { + for (exc in exceptions) { + exc.printStackTrace() + } + throw AssertionError("Test failed:\n" + exceptions.map { it.getMessage() }.makeString("\n")) + } + } + finish() + } + + private fun onBreakpoint(doOnBreakpoint: SuspendContextImpl.() -> Unit) { + super.onBreakpoint { + super.printContext(it) + it.doOnBreakpoint() + } + } + + private fun finish() { + onBreakpoint { + resume(this) + } + } + + private fun SuspendContextImpl.evaluate(expression: String, expectedResult: String) { + try { + val sourcePosition = ContextUtil.getSourcePosition(this) + val contextElement = sourcePosition?.getElementAt() + Assert.assertTrue("KotlinCodeFragmentFactory should be accepted for context element otherwise default evaluator will be called. ContextElement = ${contextElement?.getText()}", + KotlinCodeFragmentFactory().isContextAccepted(contextElement)) + + val evaluator = DebuggerInvocationUtil.commitAndRunReadAction(getProject()) { + EvaluatorBuilderImpl.build(TextWithImportsImpl(CodeFragmentKind.EXPRESSION, expression, "", JetFileType.INSTANCE), + contextElement, + sourcePosition) + } + if (evaluator == null) throw AssertionError("Cannot create an Evaluator for Evaluate Expression") + + val value = evaluator.evaluate(createEvaluationContext(this)) + val actualResult = value.asValue().toString() + Assert.assertTrue("Evaluate expression returns wrong result for $expression:\nexpected = $expectedResult\nactual = $actualResult\n", expectedResult == actualResult) + } + finally { + resume(this) + } + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java new file mode 100644 index 00000000000..64d717ce41e --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.debugger.evaluate; + +import junit.framework.Assert; +import junit.framework.Test; +import junit.framework.TestSuite; + +import java.io.File; +import java.util.regex.Pattern; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.test.InnerTestClasses; +import org.jetbrains.jet.test.TestMetadata; + +import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressionTest; + +/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("idea/testData/debugger/tinyApp/src/evaluate") +public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluateExpressionTest { + @TestMetadata("abstractFunCall.kt") + public void testAbstractFunCall() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/abstractFunCall.kt"); + } + + public void testAllFilesPresentInEvaluate() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/tinyApp/src/evaluate"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("arrays.kt") + public void testArrays() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/arrays.kt"); + } + + @TestMetadata("collections.kt") + public void testCollections() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/collections.kt"); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/simple.kt"); + } + + @TestMetadata("stdlib.kt") + public void testStdlib() throws Exception { + doTest("idea/testData/debugger/tinyApp/src/evaluate/stdlib.kt"); + } + +}