Refactored the ErrorManager and added unit tests
This commit is contained in:
parent
60a7eb562c
commit
25c0b5813b
|
@ -1,6 +1,7 @@
|
||||||
package error;
|
package error;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints error messages and potentially terminates the application.
|
* Prints error messages and potentially terminates the application.
|
||||||
|
@ -14,15 +15,23 @@ public class ErrorManager {
|
||||||
public static final String ANSI_YELLOW = "\u001B[33m";
|
public static final String ANSI_YELLOW = "\u001B[33m";
|
||||||
public static final String ANSI_PURPLE = "\u001B[35m";
|
public static final String ANSI_PURPLE = "\u001B[35m";
|
||||||
|
|
||||||
public static void generateError(LispException lispException) {
|
private Runnable systemTerminatingFunction;
|
||||||
|
private Consumer<String> outputFunction;
|
||||||
|
|
||||||
|
public ErrorManager(Runnable systemTerminatingFunction, Consumer<String> outputFunction) {
|
||||||
|
this.systemTerminatingFunction = systemTerminatingFunction;
|
||||||
|
this.outputFunction = outputFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateError(LispException lispException) {
|
||||||
String color = (lispException.getSeverity() >= CRITICAL_LEVEL) ? ANSI_PURPLE : ANSI_RED;
|
String color = (lispException.getSeverity() >= CRITICAL_LEVEL) ? ANSI_PURPLE : ANSI_RED;
|
||||||
String formattedMessage = MessageFormat.format("{0}error: {1}{2}", color, lispException.getMessage(),
|
String formattedMessage = MessageFormat.format("{0}error: {1}{2}\n", color, lispException.getMessage(),
|
||||||
ANSI_RESET);
|
ANSI_RESET);
|
||||||
|
|
||||||
System.out.println(formattedMessage);
|
outputFunction.accept(formattedMessage);
|
||||||
|
|
||||||
if (lispException.getSeverity() >= CRITICAL_LEVEL) {
|
if (lispException.getSeverity() >= CRITICAL_LEVEL) {
|
||||||
System.exit(1);
|
systemTerminatingFunction.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,10 +23,8 @@ public abstract class LispFunction {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the arguments passed to this Lisp function should be evaluated. A subclass
|
* Determine if the arguments passed to this Lisp function should be evaluated. A subclass
|
||||||
* should override this method to return <code>false</code> if it does not want its arguments to
|
* should override this method to return false if it does not want its arguments to be evaluated
|
||||||
* be evaluated prior to being passed.
|
* prior to being passed.
|
||||||
*
|
|
||||||
* @return <code>true</code>
|
|
||||||
*/
|
*/
|
||||||
public boolean evaluateArguments() {
|
public boolean evaluateArguments() {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -6,14 +6,15 @@
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
import parser.*;
|
import java.io.FileInputStream;
|
||||||
import sexpression.SExpression;
|
import java.io.FileNotFoundException;
|
||||||
import eval.*;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
import error.ErrorManager;
|
import error.ErrorManager;
|
||||||
import error.LispException;
|
import error.LispException;
|
||||||
|
import eval.EVAL;
|
||||||
import java.io.*;
|
import parser.LispParser;
|
||||||
import java.text.MessageFormat;
|
import sexpression.SExpression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is an interpreter for the Lisp programming language. It takes the name of a file as a
|
* This is an interpreter for the Lisp programming language. It takes the name of a file as a
|
||||||
|
@ -36,6 +37,7 @@ public class LispInterpreter {
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
LispParser parser = null;
|
LispParser parser = null;
|
||||||
|
ErrorManager errorManager = new ErrorManager(new TerminateInterpreter(), System.out::print);
|
||||||
boolean interactive = false;
|
boolean interactive = false;
|
||||||
|
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
|
@ -44,7 +46,7 @@ public class LispInterpreter {
|
||||||
try {
|
try {
|
||||||
parser = new LispParser(new FileInputStream(args[0]), args[0]);
|
parser = new LispParser(new FileInputStream(args[0]), args[0]);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
ErrorManager.generateError(new LispException() {
|
errorManager.generateError(new LispException() {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ -78,10 +80,10 @@ public class LispInterpreter {
|
||||||
System.out.println(result);
|
System.out.println(result);
|
||||||
} catch (LispException e) {
|
} catch (LispException e) {
|
||||||
LispInterpreter.erasePrompt(interactive);
|
LispInterpreter.erasePrompt(interactive);
|
||||||
ErrorManager.generateError(e);
|
errorManager.generateError(e);
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
LispInterpreter.erasePrompt(interactive);
|
LispInterpreter.erasePrompt(interactive);
|
||||||
ErrorManager.generateError(new LispException() {
|
errorManager.generateError(new LispException() {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@ -113,4 +115,12 @@ public class LispInterpreter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class TerminateInterpreter implements Runnable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
package error;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class ErrorManagerTester {
|
||||||
|
|
||||||
|
private static final String TERMINATED = "terminated";
|
||||||
|
private static final String MESSAGE = "message";
|
||||||
|
|
||||||
|
private ErrorManager createErrorManagerWithIndicators(Set<String> indicatorSet) {
|
||||||
|
Runnable terminationFunction = new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
indicatorSet.add(TERMINATED);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Consumer<String> outputFunction = new Consumer<String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void accept(String t) {
|
||||||
|
indicatorSet.add(MESSAGE);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return new ErrorManager(terminationFunction, outputFunction);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LispException createLispException(int severity) {
|
||||||
|
return new LispException() {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSeverity() {
|
||||||
|
return severity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return MESSAGE;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenCriticalExceptionSeverity_RunsProvidedTerminationFunction() {
|
||||||
|
Set<String> indicatorSet = new HashSet<>();
|
||||||
|
ErrorManager errorManager = createErrorManagerWithIndicators(indicatorSet);
|
||||||
|
|
||||||
|
errorManager.generateError(createLispException(ErrorManager.CRITICAL_LEVEL));
|
||||||
|
assertTrue(indicatorSet.contains(TERMINATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenNonCriticalExceptionSeverity_DoesNotRunProvidedTerminationFunction() {
|
||||||
|
Set<String> indicatorSet = new HashSet<>();
|
||||||
|
ErrorManager errorManager = createErrorManagerWithIndicators(indicatorSet);
|
||||||
|
|
||||||
|
errorManager.generateError(createLispException(0));
|
||||||
|
assertFalse(indicatorSet.contains(TERMINATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noMessageDisplayedBeforeError() {
|
||||||
|
Set<String> indicatorSet = new HashSet<>();
|
||||||
|
createErrorManagerWithIndicators(indicatorSet);
|
||||||
|
|
||||||
|
assertFalse(indicatorSet.contains(TERMINATED));
|
||||||
|
assertFalse(indicatorSet.contains(MESSAGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void usesOutputFunctionToDisplayMessages_NoTermination() {
|
||||||
|
Set<String> indicatorSet = new HashSet<>();
|
||||||
|
ErrorManager errorManager = createErrorManagerWithIndicators(indicatorSet);
|
||||||
|
|
||||||
|
errorManager.generateError(createLispException(0));
|
||||||
|
assertFalse(indicatorSet.contains(TERMINATED));
|
||||||
|
assertTrue(indicatorSet.contains(MESSAGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void usesOutputFunctionToDisplayMessages_WithTermination() {
|
||||||
|
Set<String> indicatorSet = new HashSet<>();
|
||||||
|
ErrorManager errorManager = createErrorManagerWithIndicators(indicatorSet);
|
||||||
|
|
||||||
|
errorManager.generateError(createLispException(ErrorManager.CRITICAL_LEVEL));
|
||||||
|
assertTrue(indicatorSet.contains(TERMINATED));
|
||||||
|
assertTrue(indicatorSet.contains(MESSAGE));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue