From ccac9247fe4663874be8026ab9cc968ecec7157b Mon Sep 17 00:00:00 2001 From: Michael Williamson Date: Tue, 29 Sep 2015 20:14:34 +0100 Subject: Initial commit --- .../tests/interpreter/InterpreterTests.java | 117 +++++++++++++++++++++ .../zwobble/couscous/tests/util/ExtraAsserts.java | 21 ++++ 2 files changed, 138 insertions(+) create mode 100644 src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java create mode 100644 src/test/java/org/zwobble/couscous/tests/util/ExtraAsserts.java (limited to 'src/test/java') diff --git a/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java new file mode 100644 index 0000000..d3bc21c --- /dev/null +++ b/src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java @@ -0,0 +1,117 @@ +package org.zwobble.couscous.tests.interpreter; + +import java.util.Map; + +import org.junit.Test; +import org.zwobble.couscous.Project; +import org.zwobble.couscous.ast.Assignment; +import org.zwobble.couscous.ast.ClassNode; +import org.zwobble.couscous.ast.ExpressionStatementNode; +import org.zwobble.couscous.ast.FormalArgumentNode; +import org.zwobble.couscous.ast.LiteralNode; +import org.zwobble.couscous.ast.MethodNode; +import org.zwobble.couscous.ast.ReturnNode; +import org.zwobble.couscous.interpreter.Interpreter; +import org.zwobble.couscous.interpreter.WrongNumberOfArguments; +import org.zwobble.couscous.values.InterpreterValue; +import org.zwobble.couscous.values.StringValue; + +import com.google.common.collect.ImmutableMap; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.zwobble.couscous.ast.MethodNode.staticMethod; +import static org.zwobble.couscous.ast.VariableReferenceNode.reference; +import static org.zwobble.couscous.tests.util.ExtraAsserts.assertThrows; +import static org.zwobble.couscous.values.UnitValue.UNIT; + +import lombok.val; + +public class InterpreterTests { + @Test + public void canReturnLiteralValue() { + val method = staticMethod("hello") + .statement(new ReturnNode(LiteralNode.of("hello, world!"))); + val result = runMethod(method); + + assertEquals(new StringValue("hello, world!"), result); + } + + @Test + public void canPassValueToMethod() { + val arg = new FormalArgumentNode(42, "x"); + val method = staticMethod("hello") + .argument(arg) + .statement(new ReturnNode(reference(arg))); + val result = runMethod(method, new StringValue("hello, world!")); + + assertEquals(new StringValue("hello, world!"), result); + } + + @Test + public void errorIfWrongNumberOfArgumentsArePassed() { + val method = staticMethod("hello"); + + val exception = assertThrows(WrongNumberOfArguments.class, + () -> runMethod(method, new StringValue("hello, world!"))); + + assertEquals(new WrongNumberOfArguments(0, 1), exception); + } + + @Test + public void canReassignValueToArgument() { + val arg = new FormalArgumentNode(42, "x"); + val method = staticMethod("hello") + .argument(arg) + .statement(new ExpressionStatementNode(new Assignment(reference(arg), LiteralNode.of("[updated value]")))) + .statement(new ReturnNode(reference(arg))); + val result = runMethod(method, new StringValue("[initial value]")); + + assertEquals(new StringValue("[updated value]"), result); + } + + @Test + public void valueOfAssignmentExpressionIsNewValue() { + val arg = new FormalArgumentNode(42, "x"); + val method = staticMethod("hello") + .argument(arg) + .statement(new ReturnNode(new Assignment(reference(arg), LiteralNode.of("[updated value]")))); + val result = runMethod(method, new StringValue("[initial value]")); + + assertEquals(new StringValue("[updated value]"), result); + } + + @Test + public void methodWithNoStatementsReturnsUnit() { + val method = staticMethod("hello"); + val result = runMethod(method); + + assertEquals(UNIT, result); + } + + private InterpreterValue runMethod(MethodNode.MethodNodeBuilder methodBuilder, InterpreterValue... arguments) { + val method = methodBuilder.build(); + val classNode = ClassNode.builder() + .method(method) + .build(); + val className = "com.example.Program"; + val interpreter = new Interpreter(new MapBackedProject(ImmutableMap.of( + className, classNode))); + + return interpreter.run(className, method.getName(), asList(arguments)); + } + + private static class MapBackedProject implements Project { + private Map classes; + + public MapBackedProject(Map classes) { + this.classes = classes; + } + + @Override + public ClassNode findClass(String name) { + return classes.get(name); + } + + } +} diff --git a/src/test/java/org/zwobble/couscous/tests/util/ExtraAsserts.java b/src/test/java/org/zwobble/couscous/tests/util/ExtraAsserts.java new file mode 100644 index 0000000..8b1c16c --- /dev/null +++ b/src/test/java/org/zwobble/couscous/tests/util/ExtraAsserts.java @@ -0,0 +1,21 @@ +package org.zwobble.couscous.tests.util; + +public class ExtraAsserts { + public interface Action { + void run(); + } + + @SuppressWarnings("unchecked") + public static T assertThrows(Class exceptionType, Action action) { + try { + action.run(); + throw new AssertionError("Expected exception"); + } catch (Exception exception) { + if (exceptionType.isInstance(exception)) { + return (T)exception; + } else { + throw exception; + } + } + } +} -- cgit v1.2.3