diff options
| author | Michael Williamson <mike@zwobble.org> | 2015-09-29 20:14:34 +0100 |
|---|---|---|
| committer | Michael Williamson <mike@zwobble.org> | 2015-09-29 20:14:34 +0100 |
| commit | ccac9247fe4663874be8026ab9cc968ecec7157b (patch) | |
| tree | 6e15ebf9eb130034c45f84372ce4d3776f401328 /src/test | |
Initial commit
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/java/org/zwobble/couscous/tests/interpreter/InterpreterTests.java | 117 | ||||
| -rw-r--r-- | src/test/java/org/zwobble/couscous/tests/util/ExtraAsserts.java | 21 |
2 files changed, 138 insertions, 0 deletions
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<String, ClassNode> classes; + + public MapBackedProject(Map<String, ClassNode> 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 extends Throwable> T assertThrows(Class<T> exceptionType, Action action) { + try { + action.run(); + throw new AssertionError("Expected exception"); + } catch (Exception exception) { + if (exceptionType.isInstance(exception)) { + return (T)exception; + } else { + throw exception; + } + } + } +} |
