aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/org/zwobble/couscous/tests/backends/python
diff options
context:
space:
mode:
authorMichael Williamson <mike@zwobble.org>2015-10-05 11:04:17 +0100
committerMichael Williamson <mike@zwobble.org>2015-10-05 11:04:17 +0100
commit96b1e6f776ae8ce8910c44a3bbec0b489fd10c88 (patch)
tree86658222ef741b1620c1635d3fd98d99452a387b /src/test/java/org/zwobble/couscous/tests/backends/python
parentcdf51cdb9b3f8cef5896315496f348d9f7220903 (diff)
Add the beginnings of a Python backend
Diffstat (limited to 'src/test/java/org/zwobble/couscous/tests/backends/python')
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java70
-rw-r--r--src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java80
2 files changed, 150 insertions, 0 deletions
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
new file mode 100644
index 0000000..7419aca
--- /dev/null
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonCompilerTests.java
@@ -0,0 +1,70 @@
+package org.zwobble.couscous.tests.backends.python;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.util.List;
+
+import org.zwobble.couscous.ast.ClassNode;
+import org.zwobble.couscous.backends.python.PythonCompiler;
+import org.zwobble.couscous.tests.BackendTests;
+import org.zwobble.couscous.tests.MethodRunner;
+import org.zwobble.couscous.values.InterpreterValue;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.CharStreams;
+
+import static java.lang.Integer.parseInt;
+import static java.util.Arrays.asList;
+import static org.zwobble.couscous.tests.util.ExtraFiles.deleteRecursively;
+import static org.zwobble.couscous.values.InterpreterValues.UNIT;
+import static org.zwobble.couscous.values.InterpreterValues.value;
+
+import lombok.SneakyThrows;
+import lombok.val;
+
+public class PythonCompilerTests extends BackendTests {
+ @Override
+ protected MethodRunner buildMethodRunner() {
+ return new MethodRunner() {
+ @Override
+ @SneakyThrows
+ public InterpreterValue runMethod(
+ ClassNode classNode,
+ String methodName,
+ List<InterpreterValue> arguments) {
+ val compiler = new PythonCompiler();
+ val directoryPath = Files.createTempDirectory(null);
+ try {
+ compiler.compile(asList(classNode), directoryPath);
+
+ val program = "from " + classNode.getName() + " import " + classNode.getLocalName() +
+ ";print(repr(" + classNode.getLocalName() + "." + methodName + "()))";
+
+ val process = new ProcessBuilder("python3.4", "-c", program)
+ .directory(directoryPath.toFile())
+ .start();
+ val exitCode = process.waitFor();
+ val output = readString(process.getInputStream()).trim();
+ val stderrOutput = readString(process.getErrorStream());
+ if (exitCode != 0) {
+ throw new RuntimeException("stderr was: " + stderrOutput);
+ } else if (output.equals("None")) {
+ return UNIT;
+ } else if (output.startsWith("'")) {
+ return value(output.substring(1, output.length() - 1));
+ } else {
+ return value(parseInt(output));
+ }
+ } finally {
+ deleteRecursively(directoryPath.toFile());
+ }
+ }
+
+ private String readString(final InputStream stream) throws IOException {
+ return CharStreams.toString(new InputStreamReader(stream, Charsets.UTF_8));
+ }
+ };
+ }
+}
diff --git a/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java
new file mode 100644
index 0000000..4f9b63b
--- /dev/null
+++ b/src/test/java/org/zwobble/couscous/tests/backends/python/PythonSerializerTests.java
@@ -0,0 +1,80 @@
+package org.zwobble.couscous.tests.backends.python;
+
+import org.junit.Test;
+import org.zwobble.couscous.backends.python.ast.PythonClassNode;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.zwobble.couscous.backends.python.PythonSerializer.serialize;
+import static org.zwobble.couscous.backends.python.ast.PythonFunctionDefinitionNode.pythonFunctionDefinition;
+import static org.zwobble.couscous.backends.python.ast.PythonIntegerLiteralNode.pythonIntegerLiteral;
+import static org.zwobble.couscous.backends.python.ast.PythonModuleNode.pythonModule;
+import static org.zwobble.couscous.backends.python.ast.PythonPassNode.PASS;
+import static org.zwobble.couscous.backends.python.ast.PythonReturnNode.pythonReturn;
+import static org.zwobble.couscous.backends.python.ast.PythonStringLiteralNode.pythonStringLiteral;
+
+import lombok.val;
+
+public class PythonSerializerTests {
+ @Test
+ public void integersAreNotBoxed() {
+ val output = serialize(pythonIntegerLiteral(42));
+ assertEquals("42", output);
+ }
+
+ @Test
+ public void stringsAreNotBoxed() {
+ // TODO: escaping
+ val output = serialize(pythonStringLiteral("blah"));
+ assertEquals("\"blah\"", output);
+ }
+
+ @Test
+ public void returnKeywordIsUsedForReturns() {
+ val output = serialize(pythonReturn(pythonIntegerLiteral(42)));
+ assertEquals("return 42\n", output);
+ }
+
+ @Test
+ public void passStatementIsSerializedAsPassKeyword() {
+ val output = serialize(PASS);
+ assertEquals("pass\n", output);
+ }
+
+ @Test
+ public void emptyFunctionHasPassStatement() {
+ val output = serialize(pythonFunctionDefinition("empty", asList()));
+ assertEquals("def empty():\n pass\n", output);
+ }
+
+ @Test
+ public void emptyClassHasPassStatement() {
+ val classNode = PythonClassNode.builder("Empty")
+ .build();
+ val output = serialize(classNode);
+ assertEquals("class Empty(object):\n pass\n", output);
+ }
+
+ @Test
+ public void moduleIsSerializedStatements() {
+ val classNode = pythonModule(asList(PASS));
+ val output = serialize(classNode);
+ assertEquals("pass\n", output);
+ }
+
+ @Test
+ public void bodiesOfBlocksAreIndented() {
+ val classNode = PythonClassNode.builder("Foo")
+ .statement(pythonFunctionDefinition("one", asList()))
+ .statement(pythonFunctionDefinition("two", asList()))
+ .build();
+ val output = serialize(classNode);
+ val expectedOutput =
+ "class Foo(object):\n" +
+ " def one():\n" +
+ " pass\n" +
+ " def two():\n" +
+ " pass\n";
+ assertEquals(expectedOutput, output);
+ }
+}