mirror of
https://github.com/JonathanFleischmann/CompilerULTIMATE.git
synced 2024-12-27 07:38:03 +00:00
add some e2e tests and make BytecodeTestUtil usable with different constructors
This commit is contained in:
parent
4733e77522
commit
ee2553b089
@ -1,6 +1,6 @@
|
||||
package de.maishai.typedast;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.Getter;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.MethodVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@ -16,6 +16,7 @@ public class MethodContext {
|
||||
}
|
||||
|
||||
private MethodVisitor mv;
|
||||
private Type returnType;
|
||||
private final ClassContext classContext;
|
||||
private int localVarIndex = 0;
|
||||
private final Map<String, LocalVariable> variableIndex = new HashMap<>();
|
||||
@ -26,9 +27,10 @@ public class MethodContext {
|
||||
//used to jump to the start of the loop with continue
|
||||
private final Stack<Label> continueLabels = new Stack<>();
|
||||
|
||||
public MethodContext(ClassContext classContext, MethodVisitor mv) {
|
||||
public MethodContext(ClassContext classContext, MethodVisitor mv, Type returnType) {
|
||||
this.mv = mv;
|
||||
this.classContext = classContext;
|
||||
this.returnType = returnType;
|
||||
registerVariable("this", classContext.getType());
|
||||
mv.visitCode();
|
||||
}
|
||||
@ -78,6 +80,10 @@ public class MethodContext {
|
||||
}
|
||||
|
||||
public void wrapUp() {
|
||||
//if return type is void, add return instruction
|
||||
if (returnType.getKind() == Type.Kind.VOID) {
|
||||
mv.visitInsn(Opcodes.RETURN);
|
||||
}
|
||||
System.out.println("maxStack: " + maxStack + " localVarIndex: " + localVarIndex);
|
||||
mv.visitMaxs(maxStack, localVarIndex);
|
||||
mv.visitEnd();
|
||||
|
@ -90,7 +90,7 @@ public class TypedConstructor implements TypedNode {
|
||||
int accessModifier = Opcodes.ACC_PUBLIC; // ist laut Andi ok
|
||||
MethodVisitor mv = ctx.getCw().visitMethod(accessModifier, "<init>", CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID), null, null);
|
||||
System.out.println("Visiting method: " + "<init>" + CodeGenUtils.generateDescriptor(typedParameters.stream().map(TypedParameter::getType).toList(), Type.VOID));
|
||||
MethodContext mctx = new MethodContext(ctx, mv);
|
||||
MethodContext mctx = new MethodContext(ctx, mv, Type.VOID);
|
||||
typedParameters.forEach(param -> mctx.registerVariable(param.getParaName(), param.getType()));
|
||||
//super();
|
||||
mctx.pushStack("this");
|
||||
|
@ -1,3 +1,4 @@
|
||||
import e2e.BytecodeTestUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
@ -16,7 +17,7 @@ public class CodegeneratorTests {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil testUtility = new BytecodeTestUtil("src/test/testFiles/JavaTestfilesFeatures/MethodCall.java", "MethodCall");
|
||||
|
||||
assertEquals(3, testUtility.invokeMethod("method", null));
|
||||
assertEquals(0, testUtility.invokeMethod("method", null));
|
||||
assertEquals(1, testUtility.invokeMethod("method1", new Class<?>[]{int.class}, 1));
|
||||
assertEquals(3, testUtility.invokeMethod("method2", new Class<?>[]{int.class, int.class}, 1, 2));
|
||||
});
|
||||
|
@ -1,3 +1,5 @@
|
||||
package e2e;
|
||||
|
||||
import de.maishai.Compiler;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
@ -6,8 +8,24 @@ import java.util.List;
|
||||
public class BytecodeTestUtil {
|
||||
|
||||
private Class<?> clazz;
|
||||
private Object instance;
|
||||
|
||||
public BytecodeTestUtil(String sourceFilePath, String className) throws Exception {
|
||||
clazz = loadClass(sourceFilePath, className);
|
||||
instance = clazz.getDeclaredConstructor().newInstance();
|
||||
}
|
||||
|
||||
public BytecodeTestUtil(String sourceFilePath, String className, Class<?>[] parameterTypes, Object... initargs) throws Exception {
|
||||
clazz = loadClass(sourceFilePath, className);
|
||||
instance = clazz.getDeclaredConstructor(parameterTypes).newInstance(initargs);
|
||||
}
|
||||
|
||||
public Object invokeMethod(String methodName, Class<?>[] parameterTypes, Object... args) throws Exception {
|
||||
Method method = clazz.getMethod(methodName, parameterTypes);
|
||||
return method.invoke(instance, args);
|
||||
}
|
||||
|
||||
public static Class<?> loadClass(String sourceFilePath, String className) throws Exception {
|
||||
byte[] resultBytecode = Compiler.generateByteCodeArrayFromFile(List.of(sourceFilePath)).get(0);
|
||||
|
||||
ClassLoader classLoader = new ClassLoader() {
|
||||
@ -16,13 +34,6 @@ public class BytecodeTestUtil {
|
||||
return defineClass(name, resultBytecode, 0, resultBytecode.length);
|
||||
}
|
||||
};
|
||||
clazz = classLoader.loadClass(className);
|
||||
}
|
||||
|
||||
public Object invokeMethod(String methodName, Class<?>[] parameterTypes, Object... args) throws Exception {
|
||||
Object instance = clazz.getDeclaredConstructor().newInstance();
|
||||
|
||||
Method method = clazz.getMethod(methodName, parameterTypes);
|
||||
return method.invoke(instance, args);
|
||||
return classLoader.loadClass(className);
|
||||
}
|
||||
}
|
34
src/test/java/e2e/TestConstructor.java
Normal file
34
src/test/java/e2e/TestConstructor.java
Normal file
@ -0,0 +1,34 @@
|
||||
package e2e;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
public class TestConstructor {
|
||||
|
||||
@Test
|
||||
void testConstructor_noArgAndUseGetter() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/Constructor.java", "Constructor");
|
||||
Assertions.assertEquals(12, util.invokeMethod("getX", null));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructor_withArgAndUseGetter() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/Constructor.java", "Constructor", new Class<?>[]{int.class}, 777);
|
||||
Assertions.assertEquals(777, util.invokeMethod("getX", null));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testField_setAndUseGetter() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/Constructor.java", "Constructor");
|
||||
util.invokeMethod("setX", new Class<?>[]{int.class}, 777);
|
||||
Assertions.assertEquals(777, util.invokeMethod("getX", null));
|
||||
});
|
||||
}
|
||||
}
|
33
src/test/java/e2e/TestForLoop.java
Normal file
33
src/test/java/e2e/TestForLoop.java
Normal file
@ -0,0 +1,33 @@
|
||||
package e2e;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
class TestForLoop {
|
||||
|
||||
@Test
|
||||
void testFor_simple() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/ForLoop.java", "ForLoop");
|
||||
Assertions.assertEquals(10, util.invokeMethod("simple", null));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFor_withContinue() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/ForLoop.java", "ForLoop");
|
||||
Assertions.assertEquals(8, util.invokeMethod("withContinue", null));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testFor_withBreak() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/ForLoop.java", "ForLoop");
|
||||
Assertions.assertEquals(3, util.invokeMethod("withBreak", null));
|
||||
});
|
||||
}
|
||||
}
|
33
src/test/java/e2e/TestIf.java
Normal file
33
src/test/java/e2e/TestIf.java
Normal file
@ -0,0 +1,33 @@
|
||||
package e2e;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestIf {
|
||||
|
||||
@Test
|
||||
void testIf_simple() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/If.java", "If");
|
||||
assertEquals(1, util.invokeMethod("simple", new Class<?>[]{int.class}, 1));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIf_simple2() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/If.java", "If");
|
||||
assertEquals(0, util.invokeMethod("simple", new Class<?>[]{int.class}, 0));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIf_nested() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/If.java", "If");
|
||||
assertEquals(0, util.invokeMethod("nested", new Class<?>[]{int.class}, 0));
|
||||
});
|
||||
}
|
||||
}
|
17
src/test/java/e2e/TestNewClass.java
Normal file
17
src/test/java/e2e/TestNewClass.java
Normal file
@ -0,0 +1,17 @@
|
||||
package e2e;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
public class TestNewClass {
|
||||
|
||||
@Test
|
||||
void testNew_withFields() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/NewClass.java", "NewClass");
|
||||
Assertions.assertEquals(10, util.invokeMethod("simple", null));
|
||||
});
|
||||
}
|
||||
}
|
32
src/test/java/e2e/TestWhileLoop.java
Normal file
32
src/test/java/e2e/TestWhileLoop.java
Normal file
@ -0,0 +1,32 @@
|
||||
package e2e;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
|
||||
public class TestWhileLoop {
|
||||
@Test
|
||||
void testWhile_simple() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/WhileLoop.java", "WhileLoop");
|
||||
Assertions.assertEquals(10, util.invokeMethod("simple", null));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhile_withContinue() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/WhileLoop.java", "WhileLoop");
|
||||
Assertions.assertEquals(8, util.invokeMethod("withContinue", null));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWhile_withBreak() {
|
||||
assertDoesNotThrow(() -> {
|
||||
BytecodeTestUtil util = new BytecodeTestUtil("src/test/testFiles/e2e/WhileLoop.java", "WhileLoop");
|
||||
Assertions.assertEquals(3, util.invokeMethod("withBreak", null));
|
||||
});
|
||||
}
|
||||
}
|
18
src/test/testFiles/e2e/Constructor.java
Normal file
18
src/test/testFiles/e2e/Constructor.java
Normal file
@ -0,0 +1,18 @@
|
||||
public class Constructor {
|
||||
public int x;
|
||||
public Constructor() {
|
||||
this.x = 12;
|
||||
}
|
||||
|
||||
public Constructor(int y) {
|
||||
this.x = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public void setX(int y) {
|
||||
this.x = y;
|
||||
}
|
||||
}
|
31
src/test/testFiles/e2e/ForLoop.java
Normal file
31
src/test/testFiles/e2e/ForLoop.java
Normal file
@ -0,0 +1,31 @@
|
||||
public class ForLoop {
|
||||
public int simple() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; i+=1) {
|
||||
sum += i;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public int withContinue() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; i+=1) {
|
||||
if (i == 2) {
|
||||
continue;
|
||||
}
|
||||
sum += i;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public int withBreak() {
|
||||
int sum = 0;
|
||||
for (int i = 0; i < 5; i+=1) {
|
||||
if (i == 3) {
|
||||
break;
|
||||
}
|
||||
sum += i;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
22
src/test/testFiles/e2e/If.java
Normal file
22
src/test/testFiles/e2e/If.java
Normal file
@ -0,0 +1,22 @@
|
||||
public class If {
|
||||
public int simple(int x) {
|
||||
if (x > 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public int nested(int x) {
|
||||
if (x > 0) {
|
||||
if (x > 1) {
|
||||
return 2;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
13
src/test/testFiles/e2e/NewClass.java
Normal file
13
src/test/testFiles/e2e/NewClass.java
Normal file
@ -0,0 +1,13 @@
|
||||
public class NewClass {
|
||||
public int x;
|
||||
|
||||
public NewClass() {
|
||||
x = 6;
|
||||
}
|
||||
|
||||
public int simple() {
|
||||
x = 4;
|
||||
NewClass y = new NewClass();
|
||||
return x + y.x;
|
||||
}
|
||||
}
|
38
src/test/testFiles/e2e/WhileLoop.java
Normal file
38
src/test/testFiles/e2e/WhileLoop.java
Normal file
@ -0,0 +1,38 @@
|
||||
public class WhileLoop {
|
||||
public int simple() {
|
||||
int sum = 0;
|
||||
int i = 0;
|
||||
while (i < 5) {
|
||||
sum += i;
|
||||
i += 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public int withContinue() {
|
||||
int sum = 0;
|
||||
int i = 0;
|
||||
while (i < 5) {
|
||||
if (i == 2) {
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
sum += i;
|
||||
i += 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public int withBreak() {
|
||||
int sum = 0;
|
||||
int i = 0;
|
||||
while (i < 5) {
|
||||
if (i == 3) {
|
||||
break;
|
||||
}
|
||||
sum += i;
|
||||
i += 1;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user