Refactored some code and added unit tests
This commit is contained in:
		
							parent
							
								
									62a509eb4b
								
							
						
					
					
						commit
						60a7eb562c
					
				| @ -1,5 +1,9 @@ | ||||
| package sexpression; | ||||
| 
 | ||||
| import java.text.MessageFormat; | ||||
| 
 | ||||
| import error.LispException; | ||||
| 
 | ||||
| public class LispNumber extends Atom { | ||||
| 
 | ||||
|     private int value; | ||||
| @ -10,7 +14,7 @@ public class LispNumber extends Atom { | ||||
|         try { | ||||
|             this.value = Integer.parseInt(text); | ||||
|         } catch (NumberFormatException e) { | ||||
|             throw new IllegalArgumentException(text + " is not a valid integer"); | ||||
|             throw new InvalidNumberException(text); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -28,4 +32,25 @@ public class LispNumber extends Atom { | ||||
|         return value; | ||||
|     } | ||||
| 
 | ||||
|     public class InvalidNumberException extends LispException { | ||||
| 
 | ||||
|         private static final long serialVersionUID = 1L; | ||||
|          | ||||
|         private String text; | ||||
|          | ||||
|         public InvalidNumberException(String text) { | ||||
|             this.text = text; | ||||
|         } | ||||
| 
 | ||||
|         @Override | ||||
|         public int getSeverity() { | ||||
|             return 0; | ||||
|         } | ||||
|          | ||||
|         @Override | ||||
|         public String getMessage() { | ||||
|             return MessageFormat.format("{0} is not a valid integer", text); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -2,20 +2,6 @@ package sexpression; | ||||
| 
 | ||||
| public abstract class SExpression { | ||||
| 
 | ||||
|     // for mark and sweep garbage collection | ||||
|     private boolean marked = false; | ||||
| 
 | ||||
|     public final boolean isMarked() { | ||||
|         return marked; | ||||
|     } | ||||
| 
 | ||||
|     public final void setMarked(final boolean value) { | ||||
|         marked = value; | ||||
|     } | ||||
| 
 | ||||
|     // Lisp type predicates... | ||||
|     // overridden in subclasses to describe their Lisp type | ||||
| 
 | ||||
|     public boolean nullp() { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| @ -3,8 +3,8 @@ package token; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import file.FilePosition; | ||||
| import sexpression.MalformedSExpressionException.EofEncounteredException; | ||||
| import sexpression.SExpression; | ||||
| import token.ParseException.EofEncounteredException; | ||||
| 
 | ||||
| public class Eof extends Token { | ||||
| 
 | ||||
|  | ||||
| @ -1,16 +1,15 @@ | ||||
| package sexpression; | ||||
| package token; | ||||
| 
 | ||||
| import java.text.MessageFormat; | ||||
| 
 | ||||
| import error.LispException; | ||||
| import token.Token; | ||||
| 
 | ||||
| public abstract class MalformedSExpressionException extends LispException { | ||||
| public abstract class ParseException extends LispException { | ||||
| 
 | ||||
|     private static final long serialVersionUID = 1L; | ||||
|     private Token token; | ||||
| 
 | ||||
|     public MalformedSExpressionException(Token token) { | ||||
|     public ParseException(Token token) { | ||||
|         this.token = token; | ||||
|     } | ||||
| 
 | ||||
| @ -27,7 +26,7 @@ public abstract class MalformedSExpressionException extends LispException { | ||||
| 
 | ||||
|     public abstract String getMessagePrefix(); | ||||
| 
 | ||||
|     public static class EofEncounteredException extends MalformedSExpressionException { | ||||
|     public static class EofEncounteredException extends ParseException { | ||||
| 
 | ||||
|         private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
| @ -40,7 +39,7 @@ public abstract class MalformedSExpressionException extends LispException { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static class StartsWithRightParenthesisException extends MalformedSExpressionException { | ||||
|     public static class StartsWithRightParenthesisException extends ParseException { | ||||
| 
 | ||||
|         private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
| @ -53,17 +52,4 @@ public abstract class MalformedSExpressionException extends LispException { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static class UnrecognizedTokenException extends MalformedSExpressionException { | ||||
| 
 | ||||
|         private static final long serialVersionUID = 1L; | ||||
| 
 | ||||
|         public UnrecognizedTokenException(Token token) { | ||||
|             super(token); | ||||
|         } | ||||
| 
 | ||||
|         public String getMessagePrefix() { | ||||
|             return "Unrecognized token"; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -3,9 +3,9 @@ package token; | ||||
| import java.util.function.Supplier; | ||||
| 
 | ||||
| import file.FilePosition; | ||||
| import sexpression.MalformedSExpressionException.StartsWithRightParenthesisException; | ||||
| import sexpression.Nil; | ||||
| import sexpression.SExpression; | ||||
| import token.ParseException.StartsWithRightParenthesisException; | ||||
| 
 | ||||
| public class RightParenthesis extends Token { | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| package parser; | ||||
| 
 | ||||
| import static org.junit.Assert.*; | ||||
| import static parser.SExpressionTypeAssertions.*; | ||||
| import static testutil.TestUtilities.createIOExceptionThrowingInputStream; | ||||
| import static testutil.TestUtilities.createInputStreamFromString; | ||||
| 
 | ||||
| @ -8,13 +9,12 @@ import java.io.InputStream; | ||||
| 
 | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import error.ErrorManager; | ||||
| import error.LispException; | ||||
| import scanner.LispInputStream.UncheckedIOException; | ||||
| import scanner.LispScanner.UnterminatedStringException; | ||||
| import sexpression.MalformedSExpressionException.EofEncounteredException; | ||||
| import sexpression.MalformedSExpressionException.StartsWithRightParenthesisException; | ||||
| import sexpression.Nil; | ||||
| import sexpression.SExpression; | ||||
| import token.ParseException.EofEncounteredException; | ||||
| import token.ParseException.StartsWithRightParenthesisException; | ||||
| import token.TokenFactory.BadCharacterException; | ||||
| 
 | ||||
| public class LispParserTester { | ||||
| @ -29,64 +29,6 @@ public class LispParserTester { | ||||
|         return new LispParser(stringInputStream, "testFile"); | ||||
|     } | ||||
| 
 | ||||
|     private void assertList(SExpression sExpression) { | ||||
|         assertFalse(sExpression.atomp()); | ||||
|         assertTrue(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertTrue(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertFalse(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     private void assertNil(SExpression sExpression) { | ||||
|         assertEquals(sExpression, Nil.getUniqueInstance()); | ||||
| 
 | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertTrue(sExpression.listp()); | ||||
|         assertTrue(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertTrue(sExpression.symbolp()); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private void assertNumber(SExpression sExpression) { | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertFalse(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertTrue(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertFalse(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     private void assertString(SExpression sExpression) { | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertFalse(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertTrue(sExpression.stringp()); | ||||
|         assertFalse(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     private void assertSymbol(SExpression sExpression) { | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertFalse(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertTrue(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testEofMethod_ReturnsTrueWithNoInput() { | ||||
|         String input = ""; | ||||
| @ -107,8 +49,8 @@ public class LispParserTester { | ||||
|     public void testEofMethod_ReturnsTrueAfterSomeInput() { | ||||
|         String input = "(yyz 9 9 9)"; | ||||
|         LispParser parser = createLispParser(input); | ||||
|         parser.getNextSExpression(); | ||||
| 
 | ||||
|         parser.getNextSExpression(); | ||||
|         assertTrue(parser.isEof()); | ||||
|     } | ||||
| 
 | ||||
| @ -116,6 +58,7 @@ public class LispParserTester { | ||||
|     public void testEofMethod_ReturnsFalseAfterMultipleExpressions() { | ||||
|         String input = "()()()"; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         assertFalse(parser.isEof()); | ||||
|         parser.getNextSExpression(); | ||||
|         assertFalse(parser.isEof()); | ||||
| @ -127,6 +70,7 @@ public class LispParserTester { | ||||
|     public void testEofMethod_ReturnsTrueAfterMultipleExpressions() { | ||||
|         String input = "()()()"; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         assertFalse(parser.isEof()); | ||||
|         parser.getNextSExpression(); | ||||
|         assertFalse(parser.isEof()); | ||||
| @ -238,6 +182,33 @@ public class LispParserTester { | ||||
|         parser.getNextSExpression(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenBadToken_ExceptionHasCorrectSeverity() { | ||||
|         String input = "["; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         try { | ||||
|             parser.getNextSExpression(); | ||||
|         } catch (BadCharacterException e) { | ||||
|             assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenBadToken_ExceptionHasMessageText() { | ||||
|         String input = "["; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         try { | ||||
|             parser.getNextSExpression(); | ||||
|         } catch (BadCharacterException e) { | ||||
|             String message = e.getMessage(); | ||||
| 
 | ||||
|             assertNotNull(message); | ||||
|             assertTrue(message.length() > 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test(expected = UnterminatedStringException.class) | ||||
|     public void givenUnterminatedString_ThrowsException() { | ||||
|         String input = "\"string"; | ||||
| @ -254,6 +225,33 @@ public class LispParserTester { | ||||
|         parser.getNextSExpression(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenUnterminatedList_ExceptionHasCorrectSeverity() { | ||||
|         String input = "(bad list"; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         try { | ||||
|             parser.getNextSExpression(); | ||||
|         } catch (EofEncounteredException e) { | ||||
|             assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenUnterminatedList_ExceptionHasMessage() { | ||||
|         String input = "(bad list"; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         try { | ||||
|             parser.getNextSExpression(); | ||||
|         } catch (EofEncounteredException e) { | ||||
|             String message = e.getMessage(); | ||||
| 
 | ||||
|             assertNotNull(message); | ||||
|             assertTrue(message.length() > 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test(expected = StartsWithRightParenthesisException.class) | ||||
|     public void givenUnmatchedRightParenthesis_ThrowsException() { | ||||
|         String input = ")"; | ||||
| @ -262,6 +260,33 @@ public class LispParserTester { | ||||
|         parser.getNextSExpression(); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenUnmatchedRightParenthesis_ExceptionHasCorrectSeverity() { | ||||
|         String input = ")"; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         try { | ||||
|             parser.getNextSExpression(); | ||||
|         } catch (StartsWithRightParenthesisException e) { | ||||
|             assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void givenUnmatchedRightParenthesis_ExceptionHasMessage() { | ||||
|         String input = ")"; | ||||
|         LispParser parser = createLispParser(input); | ||||
| 
 | ||||
|         try { | ||||
|             parser.getNextSExpression(); | ||||
|         } catch (StartsWithRightParenthesisException e) { | ||||
|             String message = e.getMessage(); | ||||
| 
 | ||||
|             assertNotNull(message); | ||||
|             assertTrue(message.length() > 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test(expected = BadCharacterException.class) | ||||
|     public void givenBadCharacter_ThrowsExceptionAfterEofCalled() { | ||||
|         String input = "["; | ||||
|  | ||||
							
								
								
									
										68
									
								
								test/parser/SExpressionTypeAssertions.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								test/parser/SExpressionTypeAssertions.java
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| package parser; | ||||
| 
 | ||||
| import static org.junit.Assert.*; | ||||
| 
 | ||||
| import sexpression.Nil; | ||||
| import sexpression.SExpression; | ||||
| 
 | ||||
| public final class SExpressionTypeAssertions { | ||||
| 
 | ||||
|     public static void assertList(SExpression sExpression) { | ||||
|         assertFalse(sExpression.atomp()); | ||||
|         assertTrue(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertTrue(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertFalse(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     public static void assertNil(SExpression sExpression) { | ||||
|         assertEquals(sExpression, Nil.getUniqueInstance()); | ||||
| 
 | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertTrue(sExpression.listp()); | ||||
|         assertTrue(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertTrue(sExpression.symbolp()); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     public static void assertNumber(SExpression sExpression) { | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertFalse(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertTrue(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertFalse(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     public static void assertString(SExpression sExpression) { | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertFalse(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertTrue(sExpression.stringp()); | ||||
|         assertFalse(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
|     public static void assertSymbol(SExpression sExpression) { | ||||
|         assertTrue(sExpression.atomp()); | ||||
|         assertFalse(sExpression.consp()); | ||||
|         assertFalse(sExpression.functionp()); | ||||
|         assertFalse(sExpression.listp()); | ||||
|         assertFalse(sExpression.nullp()); | ||||
|         assertFalse(sExpression.numberp()); | ||||
|         assertFalse(sExpression.stringp()); | ||||
|         assertTrue(sExpression.symbolp()); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,10 +1,13 @@ | ||||
| package sexpression; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.*; | ||||
| 
 | ||||
| import org.junit.Before; | ||||
| import org.junit.Test; | ||||
| 
 | ||||
| import error.ErrorManager; | ||||
| import sexpression.LispNumber.InvalidNumberException; | ||||
| 
 | ||||
| public class SExpressionTester { | ||||
| 
 | ||||
|     private void assertSExpressionMatchesString(String expected, SExpression sExpression) { | ||||
| @ -67,4 +70,72 @@ public class SExpressionTester { | ||||
|         assertSExpressionMatchesString(expected, list); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testConsWithNonListCdrToString() { | ||||
|         String expected = "(A . B)"; | ||||
|         Cons list = new Cons(new Symbol("A"), new Symbol("B")); | ||||
| 
 | ||||
|         assertSExpressionMatchesString(expected, list); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testCarOfNilIsNil() { | ||||
|         assertEquals(Nil.getUniqueInstance().getCar(), Nil.getUniqueInstance()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testCdrOfNilIsNil() { | ||||
|         assertEquals(Nil.getUniqueInstance().getCdr(), Nil.getUniqueInstance()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void afterSettingCarOfNil_ShouldStillBeNil() { | ||||
|         Cons nil = Nil.getUniqueInstance(); | ||||
|         nil.setCar(new LispNumber(2)); | ||||
| 
 | ||||
|         assertEquals(nil.getCar(), Nil.getUniqueInstance()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void afterSettingCdrOfNil_ShouldStillBeNil() { | ||||
|         Cons nil = Nil.getUniqueInstance(); | ||||
|         nil.setCdr(new LispNumber(2)); | ||||
| 
 | ||||
|         assertEquals(nil.getCdr(), Nil.getUniqueInstance()); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testNumberValue() { | ||||
|         int value = 12; | ||||
|         LispNumber number = new LispNumber(String.valueOf(value)); | ||||
| 
 | ||||
|         assertEquals(number.getValue(), value); | ||||
|     } | ||||
| 
 | ||||
|     @Test(expected = InvalidNumberException.class) | ||||
|     public void testInvalidNumberText_ThrowsException() { | ||||
|         new LispNumber("a"); | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testInvalidNumberException_HasCorrectSeverity() { | ||||
|         try { | ||||
|             new LispNumber("a"); | ||||
|         } catch (InvalidNumberException e) { | ||||
|             assertTrue(e.getSeverity() < ErrorManager.CRITICAL_LEVEL); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     public void testInvalidNumberException_HasMessageText() { | ||||
|         try { | ||||
|             new LispNumber("a"); | ||||
|         } catch (InvalidNumberException e) { | ||||
|             String message = e.getMessage(); | ||||
| 
 | ||||
|             assertNotNull(message); | ||||
|             assertTrue(message.length() > 0); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -2,7 +2,7 @@ package testutil; | ||||
| 
 | ||||
| import java.io.*; | ||||
| 
 | ||||
| public class TestUtilities { | ||||
| public final class TestUtilities { | ||||
| 
 | ||||
|     public static InputStream createInputStreamFromString(String string) { | ||||
|         return new ByteArrayInputStream(string.getBytes()); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user