implement junit tests

This commit is contained in:
2020-03-09 21:32:05 +01:00
parent 649e690ac4
commit 9df0da89ff
14 changed files with 399 additions and 0 deletions

View File

@@ -0,0 +1,21 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class AndTest {
@Test
void onlyForBool() {
ParseTree tree = Helper.prepareParser("function foo(): bool { return 1 && 2; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:30 && is only defined for bool.", e.getMessage());
}
}

View File

@@ -0,0 +1,43 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class ConstructorCallTest {
@Test
void structNotDefined() {
ParseTree tree = Helper.prepareParser("struct bar { a: int; } function foo(): bar { return create schwurbel(1); } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:52 Struct with name \"schwurbel\" not defined.", e.getMessage());
}
@Test
void numConstructorParameterMissmatch() {
ParseTree tree = Helper.prepareParser("struct bar { a: int; } function foo(): bar { return create bar(1, false); } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:52 Struct \"bar\" defined 1 fields, but got 2 constructor parameters.", e.getMessage());
}
@Test
void constructorParameterTypeMismatch() {
ParseTree tree = Helper.prepareParser("struct bar { a: int; } function foo(): bar { return create bar(false); } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:63 argument 0 Type missmatch: cannot combine bool and int", e.getMessage());
}
}

View File

@@ -0,0 +1,21 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class DestroyStatementTest {
@Test
void variableNotDefined() {
ParseTree tree = Helper.prepareParser("struct bar { a: int; } function foo(): int { destroy x; return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:45 Variable with name \"x\" not defined.", e.getMessage());
}
}

View File

@@ -0,0 +1,32 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class FieldAssignmentTest {
@Test
void variableNotDefined() {
ParseTree tree = Helper.prepareParser("struct test { a: int; } function foo(): int { str.a = 1; return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:46 Variable with name str not defined.", e.getMessage());
}
@Test
void fieldAssignmentOnNonStruct() {
ParseTree tree = Helper.prepareParser("struct test { a: int; } function foo(): int { let x: int = 0; x.a = 0; return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:62 Variable must reference a struct but references int.", e.getMessage());
}
}

View File

@@ -0,0 +1,43 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class FunctionCallTest {
@Test
void funcNotDefined() {
ParseTree tree = Helper.prepareParser("function foo(): int { return 1; } bar();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:34 Function with name \"bar\" not defined.", e.getMessage());
}
@Test
void numParameterMismatch() {
ParseTree tree = Helper.prepareParser("function foo(): int { return 1; } foo(5);");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:34 Function \"foo\" expects 0 parameters, but got 1.", e.getMessage());
}
@Test
void parameterTypeMissmatch() {
ParseTree tree = Helper.prepareParser("function foo(x: int): int { return x; } foo(false);");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:40 argument 0 Expected int but got: bool", e.getMessage());
}
}

View File

@@ -0,0 +1,32 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class FunctionDefinitionTest {
@Test
void typeNotDefined() {
ParseTree tree = Helper.prepareParser("function foo(): schwurbel { return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:0 Type schwurbel not defined.", e.getMessage());
}
@Test
void noReturnExpression() {
ParseTree tree = Helper.prepareParser("function foo(): int { let x: int; x = 0; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:0 Function foo has to return something of type int.", e.getMessage());
}
}

36
src/test/java/Helper.java Normal file
View File

@@ -0,0 +1,36 @@
import java.util.*;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;
import de.hsrm.compiler.Klang.*;
import de.hsrm.compiler.Klang.helper.*;
import de.hsrm.compiler.Klang.nodes.*;
public class Helper {
public static ParseTree prepareParser(String input) {
CharStream inStream = CharStreams.fromString(input);
KlangLexer lexer = new KlangLexer(inStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
KlangParser parser = new KlangParser(tokens);
return parser.parse();
}
public static Map<String, FunctionInformation> getFuncs(ParseTree tree) {
var functionDefinitions = new HashMap<String, FunctionInformation>();
new GetFunctions(functionDefinitions).visit(tree);
return functionDefinitions;
}
public static Set<String> getStructNames(ParseTree tree) {
var structNames = new HashSet<String>();
new GetStructNames(structNames).visit(tree);
return structNames;
}
public static Map<String, StructDefinition> getStructs(ParseTree tree) {
var structs = new HashMap<String, StructDefinition>();
new GetStructs(getStructNames(tree), structs).visit(tree);
return structs;
}
}

View File

@@ -0,0 +1,20 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class ModuloTest {
@Test
void onlyForInt() {
ParseTree tree = Helper.prepareParser("function foo(): float { return 1.0 % 2.3; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:31 Only integers are allowed for modulo.", e.getMessage());
}
}

21
src/test/java/OrTest.java Normal file
View File

@@ -0,0 +1,21 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class OrTest {
@Test
void onlyForBool() {
ParseTree tree = Helper.prepareParser("function foo(): bool { return 1 || 2; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:30 || is only defined for bool.", e.getMessage());
}
}

View File

@@ -0,0 +1,14 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
public class ParameterTest {
@Test
void typeNotDefined() {
ParseTree tree = Helper.prepareParser("struct test { a: schwurbel; } function foo(): int { return 1; } foo();");
Exception e = assertThrows(RuntimeException.class, () -> Helper.getStructs(tree));
assertEquals("Error in line 1:14 Type schwurbel not defined.", e.getMessage());
}
}

View File

@@ -0,0 +1,31 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class StructFieldAccessTest {
@Test
void variableNotDefined() {
ParseTree tree = Helper.prepareParser("struct test { a: int; } function foo(): int { return str.a; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:53 Variable with name str not defined.", e.getMessage());
}
@Test
void fieldAssignmentOnNonStruct() {
ParseTree tree = Helper.prepareParser("struct test { a: int; } function foo(): int { let x: int = 0; return x.a; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:69 Variable must reference a struct but references int.", e.getMessage());
}
}

View File

@@ -0,0 +1,21 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class VariableAssignmentTest {
@Test
void variableNotDefined() {
ParseTree tree = Helper.prepareParser("function foo(): int { x = 1; return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:22 Variable with name \"x\" not defined.", e.getMessage());
}
}

View File

@@ -0,0 +1,32 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class VariableDeclarationTest {
@Test
void typeNotDefined() {
ParseTree tree = Helper.prepareParser("function foo(): int { let X: unk; return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:22 Type unk not defined.", e.getMessage());
}
@Test
void variableRedeclaration()
{
ParseTree tree = Helper.prepareParser("function foo(): int { let x: int; let x: bool; return 1; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:34 Redeclaration of variable with name \"x\".", e.getMessage());
}
}

View File

@@ -0,0 +1,32 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.antlr.v4.runtime.tree.ParseTree;
import org.junit.jupiter.api.Test;
import de.hsrm.compiler.Klang.ContextAnalysis;
public class VariableTest {
@Test
void variableNotDefined() {
ParseTree tree = Helper.prepareParser("function foo(): int { return x; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:29 Variable with name \"x\" not defined.", e.getMessage());
}
@Test
void variableNotInitialized() {
ParseTree tree = Helper.prepareParser("function foo(): int { let x: int; return x; } foo();");
var funcs = Helper.getFuncs(tree);
var structs = Helper.getStructs(tree);
ContextAnalysis ctxAnal = new ContextAnalysis(funcs, structs);
Exception e = assertThrows(RuntimeException.class, () -> ctxAnal.visit(tree));
assertEquals("Error in line 1:41 Variable with name \"x\" has not been initialized.", e.getMessage());
}
}