diff --git a/src/test/interpreter/VisitorUnitTest.java b/src/test/interpreter/VisitorUnitTest.java index 39a1fa1..ccc9fdc 100644 --- a/src/test/interpreter/VisitorUnitTest.java +++ b/src/test/interpreter/VisitorUnitTest.java @@ -3,10 +3,14 @@ import interpreter.antlr.MineScriptParser; import interpreter.types.*; import interpreter.utils.MockTerminalNode; +import interpreter.utils.MockToken; +import org.antlr.v4.runtime.Token; +import org.jetbrains.annotations.NotNull; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; import org.mockito.Mock; @@ -14,6 +18,7 @@ import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.Objects; import java.util.concurrent.atomic.AtomicReference; @ExtendWith(MockitoExtension.class) @@ -23,7 +28,8 @@ class VisitorUnitTest { @Spy private final Visitor spyVisitor = visitor; @Mock private MineScriptParser.AssignContext mockAssignContext; - @Mock private MineScriptParser.ExpressionContext mockExpressionContext; + @Mock private MineScriptParser.ExpressionContext mockExpressionContext1; + @Mock private MineScriptParser.ExpressionContext mockExpressionContext2; @Mock private MineScriptParser.BoolContext mockBoolContext; @Mock private MineScriptParser.AbsDirContext mockAbsDirContext; @Mock private MineScriptParser.RelDirContext mockRelDirContext; @@ -31,14 +37,17 @@ class VisitorUnitTest { @Mock private MineScriptParser.IdContext mockIdContext; @Mock private MineScriptParser.NegContext mockNegContext; @Mock private MineScriptParser.NotExprContext mockNotExprContext; + @Mock private MineScriptParser.AddSubContext mockAddSubContext; + + @ParameterizedTest @ValueSource(ints = {-1000, -10, 0, 10, 1000}) void visitAssignStoresCorrectNumber(int value) { // Mock functions ID(), expression(), and visit() Mockito.when(mockAssignContext.ID()).thenReturn(new MockTerminalNode("varName")); - Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSNumber(value)); + Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSNumber(value)); // Call the visitAssign method on the spy MSType result = spyVisitor.visitAssign(mockAssignContext); @@ -57,8 +66,8 @@ void visitAssignStoresCorrectNumber(int value) { void visitAssignStoresCorrectBoolean(boolean value) { // Mock functions ID(), expression(), and visit() Mockito.when(mockAssignContext.ID()).thenReturn(new MockTerminalNode("varName")); - Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSBool(value)); + Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSBool(value)); // Call the visitAssign method on the spy MSType result = spyVisitor.visitAssign(mockAssignContext); @@ -77,8 +86,8 @@ void visitAssignStoresCorrectBoolean(boolean value) { void visitAssignStoresCorrectRelDir(MSRelDir.Direction value) { // Mock functions ID(), expression(), and visit() Mockito.when(mockAssignContext.ID()).thenReturn(new MockTerminalNode("varName")); - Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSRelDir(value.toString().toLowerCase())); + Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSRelDir(value.toString().toLowerCase())); // Call the visitAssign method on the spy MSType result = spyVisitor.visitAssign(mockAssignContext); @@ -97,8 +106,8 @@ void visitAssignStoresCorrectRelDir(MSRelDir.Direction value) { void visitAssignStoresCorrectAbsDir(MSAbsDir.Direction value) { // Mock functions ID(), expression(), and visit() Mockito.when(mockAssignContext.ID()).thenReturn(new MockTerminalNode("varName")); - Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSAbsDir(value.toString().toLowerCase())); + Mockito.when(mockAssignContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSAbsDir(value.toString().toLowerCase())); // Call the visitAssign method on the spy MSType result = spyVisitor.visitAssign(mockAssignContext); @@ -114,8 +123,8 @@ void visitAssignStoresCorrectAbsDir(MSAbsDir.Direction value) { @Test void visitNotExprValidBoolReturnsNegatedBool() { - Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSBool(false)); + Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSBool(false)); MSType result = spyVisitor.visitNotExpr(mockNotExprContext); Assertions.assertTrue(((MSBool) result).getValue()); @@ -123,8 +132,8 @@ void visitNotExprValidBoolReturnsNegatedBool() { @Test void visitNotExprPassZeroReturnsTrue() { - Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSNumber(0)); + Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSNumber(0)); MSType result = spyVisitor.visitNotExpr(mockNotExprContext); Assertions.assertTrue(((MSBool) result).getValue()); @@ -133,8 +142,8 @@ void visitNotExprPassZeroReturnsTrue() { @ParameterizedTest @ValueSource(ints = {-1000, -100, 100, 1000}) void visitNotExprPassNonZeroNumberReturnsFalse(int value) { - Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSNumber(value)); + Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSNumber(value)); MSType result = spyVisitor.visitNotExpr(mockNotExprContext); Assertions.assertFalse(((MSBool) result).getValue()); @@ -142,8 +151,8 @@ void visitNotExprPassNonZeroNumberReturnsFalse(int value) { @Test void visitNotExprInvalidTypeThrowsRuntimeException() { - Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSRelDir("right")); + Mockito.when(mockNotExprContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSRelDir("right")); Assertions.assertThrows(RuntimeException.class, () -> spyVisitor.visitNotExpr(mockNotExprContext)); } @@ -151,8 +160,8 @@ void visitNotExprInvalidTypeThrowsRuntimeException() { @ParameterizedTest @ValueSource(ints = {-1000, -10, 0, 10, 1000}) void visitNegNegatesNumber(int value) { - Mockito.when(mockNegContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSNumber(value)); + Mockito.when(mockNegContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSNumber(value)); MSType result = spyVisitor.visitNeg(mockNegContext); Assertions.assertEquals(-value, ((MSNumber) result).getValue()); @@ -160,8 +169,8 @@ void visitNegNegatesNumber(int value) { @Test void visitNegInvalidTypeThrowsRuntimeException() { - Mockito.when(mockNegContext.expression()).thenReturn(mockExpressionContext); - Mockito.when(spyVisitor.visit(mockExpressionContext)).thenReturn(new MSBool(false)); + Mockito.when(mockNegContext.expression()).thenReturn(mockExpressionContext1); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSBool(false)); Assertions.assertThrows(RuntimeException.class, () -> spyVisitor.visitNeg(mockNegContext)); } @@ -250,4 +259,22 @@ void visitNumberInvalidInputThrowsRuntimeException(){ Mockito.when(mockNumberContext.NUMBER()).thenReturn(new MockTerminalNode("abc")); Assertions.assertThrows(RuntimeException.class, () -> spyVisitor.visitNumber(mockNumberContext)); } + + @ParameterizedTest + @CsvSource ({"1, 2, +", "2, 1, -", "0, 0, +", "-1, -2, +", "-2, -1, -"}) + void visitAddSubValidInputReturnsNumber(int value1, int value2, String operator){ + mockAddSubContext.op = new MockToken(operator); + Mockito.when(mockAddSubContext.expression(0)).thenReturn(mockExpressionContext1); + Mockito.when(mockAddSubContext.expression(1)).thenReturn(mockExpressionContext2); + Mockito.when(spyVisitor.visit(mockExpressionContext1)).thenReturn(new MSNumber(value1)); + Mockito.when(spyVisitor.visit(mockExpressionContext2)).thenReturn(new MSNumber(value2)); + + MSType result = spyVisitor.visitAddSub(mockAddSubContext); + if (operator.equals("+")){ + Assertions.assertEquals(value1 + value2, ((MSNumber) result).getValue()); + } else if (operator.equals("-")){ + Assertions.assertEquals(value1 - value2, ((MSNumber) result).getValue()); + } + } + } diff --git a/src/test/interpreter/utils/MockToken.java b/src/test/interpreter/utils/MockToken.java new file mode 100644 index 0000000..b28687f --- /dev/null +++ b/src/test/interpreter/utils/MockToken.java @@ -0,0 +1,58 @@ +package interpreter.utils; + +import org.antlr.v4.runtime.CharStream; +import org.antlr.v4.runtime.Token; +import org.antlr.v4.runtime.TokenSource; + +public record MockToken(String token) implements Token { + + @Override + public String getText() { + return token; + } + + @Override + public int getType() { + return 0; + } + + @Override + public int getLine() { + return 0; + } + + @Override + public int getCharPositionInLine() { + return 0; + } + + @Override + public int getChannel() { + return 0; + } + + @Override + public int getTokenIndex() { + return 0; + } + + @Override + public int getStartIndex() { + return 0; + } + + @Override + public int getStopIndex() { + return 0; + } + + @Override + public TokenSource getTokenSource() { + return null; + } + + @Override + public CharStream getInputStream() { + return null; + } +}