diff --git a/eval4j.iml b/eval4j.iml
index 14b55ac72e5..cc20df994ed 100644
--- a/eval4j.iml
+++ b/eval4j.iml
@@ -4,6 +4,7 @@
+
diff --git a/test/org/jetbrains/eval4j/test/TestData.java b/test/org/jetbrains/eval4j/test/TestData.java
new file mode 100644
index 00000000000..66593712f11
--- /dev/null
+++ b/test/org/jetbrains/eval4j/test/TestData.java
@@ -0,0 +1,9 @@
+package org.jetbrains.eval4j.test;
+
+public class TestData {
+ public void imNotAPAckage() {}
+
+ public static int testReturn() {
+ return 2;
+ }
+}
diff --git a/test/org/jetbrains/eval4j/test/main.kt b/test/org/jetbrains/eval4j/test/main.kt
new file mode 100644
index 00000000000..d651f6f4c4b
--- /dev/null
+++ b/test/org/jetbrains/eval4j/test/main.kt
@@ -0,0 +1,137 @@
+package org.jetbrains.eval4j.test
+
+import org.objectweb.asm.*
+import org.objectweb.asm.Opcodes.*
+import org.objectweb.asm.tree.MethodNode
+import java.lang.reflect.Modifier
+import org.jetbrains.eval4j.*
+import org.junit.Assert.*
+import junit.framework.TestSuite
+import junit.framework.TestCase
+
+fun suite(): TestSuite {
+ val suite = TestSuite()
+
+ val ownerClass = javaClass()
+ val inputStream = ownerClass.getClassLoader()!!.getResourceAsStream(ownerClass.getInternalName() + ".class")!!
+
+ ClassReader(inputStream).accept(object : ClassVisitor(ASM4) {
+
+ override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? {
+ return object : MethodNode(access, name, desc, signature, exceptions) {
+ override fun visitEnd() {
+ val testCase = doTest(ownerClass, this)
+ if (testCase != null) {
+ suite.addTest(testCase)
+ }
+ }
+ }
+ }
+ }, 0)
+
+ return suite
+}
+
+fun Class<*>.getInternalName(): String = Type.getType(this).getInternalName()
+
+fun doTest(ownerClass: Class, methodNode: MethodNode): TestCase? {
+ var expected: InterpreterResult? = null
+ for (method in ownerClass.getMethods()) {
+ if (method.getName() == methodNode.name) {
+ if ((method.getModifiers() and Modifier.STATIC) == 0) {
+ println("Skipping instance method: $method")
+ }
+ else if (method.getParameterTypes()!!.size > 0) {
+ println("Skipping method with parameters: $method")
+ }
+ else {
+ method.setAccessible(true)
+ val result = method.invoke(null)
+ val returnType = Type.getType(method.getReturnType()!!)
+ expected = when (returnType.getSort()) {
+ Type.VOID -> ValueReturned(VOID_VALUE)
+ Type.BOOLEAN -> ValueReturned(boolean(result as Boolean))
+ Type.BYTE -> ValueReturned(byte(result as Byte))
+ Type.SHORT -> ValueReturned(short(result as Short))
+ Type.CHAR -> ValueReturned(char(result as Char))
+ Type.INT -> ValueReturned(int(result as Int))
+ Type.LONG -> ValueReturned(long(result as Long))
+ Type.DOUBLE -> ValueReturned(double(result as Double))
+ Type.FLOAT -> ValueReturned(float(result as Float))
+ Type.OBJECT -> ValueReturned(obj(result))
+ else -> {
+ println("Unsupported result type: $returnType")
+ return null
+ }
+ }
+ println("Testing $method")
+ }
+ }
+ }
+
+ if (expected == null) {
+ println("Method not found: ${methodNode.name}")
+ return null
+ }
+
+ return object : TestCase(methodNode.name) {
+
+ override fun runTest() {
+ val value = interpreterLoop(
+ ownerClass.getInternalName(),
+ methodNode,
+ REFLECTION_EVAL
+ )
+
+ assertEquals(value, expected)
+ }
+ }
+}
+
+object REFLECTION_EVAL : Eval {
+ override fun loadClass(classType: Type): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun newInstance(classType: Type): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun checkCast(value: Value, targetType: Type): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun isInsetanceOf(value: Value, targetType: Type): Boolean {
+ throw UnsupportedOperationException()
+ }
+ override fun newArray(arrayType: Type, size: Int): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun newMultiDimensionalArray(arrayType: Type, dimensionSizes: List): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun getArrayLength(array: Value): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun getArrayElement(array: Value, index: Value): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun setArrayElement(array: Value, index: Value, newValue: Value) {
+ throw UnsupportedOperationException()
+ }
+ override fun getStaticField(fieldDesc: String): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun setStaticField(fieldDesc: String, newValue: Value) {
+ throw UnsupportedOperationException()
+ }
+ override fun invokeStaticMethod(methodDesc: String, arguments: List): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun getField(instance: Value, fieldDesc: String): Value {
+ throw UnsupportedOperationException()
+ }
+ override fun setField(instance: Value, fieldDesc: String, newValue: Value) {
+ throw UnsupportedOperationException()
+ }
+ override fun invokeMethod(instance: Value, methodDesc: String, arguments: List, invokespecial: Boolean): Value {
+ throw UnsupportedOperationException()
+ }
+}
\ No newline at end of file