Increase test coverage and refactor code
This commit is contained in:
parent
79fb8b633b
commit
23dd1c0654
|
@ -1,9 +1,9 @@
|
|||
package error;
|
||||
|
||||
import static error.ErrorManager.Severity.*;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
|
||||
|
@ -40,7 +40,7 @@ public class ErrorManager {
|
|||
private String formatMessage(LispException lispException) {
|
||||
Severity severity = lispException.getSeverity();
|
||||
String prefix = severity.toDisplayString();
|
||||
String message = MessageFormat.format("[{0}] {1}", prefix, lispException.getMessage());
|
||||
String message = format("[{0}] {1}", prefix, lispException.getMessage());
|
||||
|
||||
return severity.decorate(message, environment);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package error;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import file.FilePosition;
|
||||
|
||||
|
@ -15,8 +15,8 @@ public abstract class LineColumnException extends LispException {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("{0} - line {1}, column {2}", getMessagePrefix(), position.getLineNumber(),
|
||||
position.getColumnNumber());
|
||||
return format("{0} - line {1}, column {2}", getMessagePrefix(), position.getLineNumber(),
|
||||
position.getColumnNumber());
|
||||
}
|
||||
|
||||
public abstract String getMessagePrefix();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package function;
|
||||
|
||||
import static function.builtin.cons.LENGTH.getLength;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
import sexpression.*;
|
||||
|
@ -163,7 +163,7 @@ public class ArgumentValidator {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("too few arguments given to {0}: {1}", functionName, argumentList);
|
||||
return format("too few arguments given to {0}: {1}", functionName, argumentList);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ public class ArgumentValidator {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("too many arguments given to {0}: {1}", functionName, argumentList);
|
||||
return format("too many arguments given to {0}: {1}", functionName, argumentList);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,7 +197,7 @@ public class ArgumentValidator {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("dotted argument list given to {0}: {1}", functionName, argumentList);
|
||||
return format("dotted argument list given to {0}: {1}", functionName, argumentList);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,8 +217,8 @@ public class ArgumentValidator {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("{0}: {1} is not the expected type of ''{2}''", functionName, argument,
|
||||
getExpectedTypeName());
|
||||
return format("{0}: {1} is not the expected type of ''{2}''", functionName, argument,
|
||||
getExpectedTypeName());
|
||||
}
|
||||
|
||||
private String getExpectedTypeName() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package function;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static sexpression.Nil.NIL;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import error.LispException;
|
||||
|
@ -140,8 +140,8 @@ public class UserDefinedFunction extends LispFunction {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("unexpected parameters following ''&rest'' in definition of {0}: {1}",
|
||||
functionName, parameters);
|
||||
return format("unexpected parameters following ''&rest'' in definition of {0}: {1}", functionName,
|
||||
parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,11 @@ package function.builtin;
|
|||
|
||||
import static function.builtin.cons.LIST.makeList;
|
||||
import static function.builtin.special.LAMBDA.*;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import static table.FunctionTable.lookupFunction;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
import function.*;
|
||||
import sexpression.*;
|
||||
|
@ -150,7 +149,7 @@ public class EVAL extends LispFunction {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("undefined function: {0}", function);
|
||||
return format("undefined function: {0}", function);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -165,7 +164,7 @@ public class EVAL extends LispFunction {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("symbol {0} has no value", symbol);
|
||||
return format("symbol {0} has no value", symbol);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package function.builtin;
|
||||
|
||||
import static function.builtin.EVAL.eval;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static sexpression.Nil.NIL;
|
||||
import static sexpression.Symbol.T;
|
||||
import static util.Path.getPathPrefix;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Stack;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
|
@ -105,7 +105,7 @@ public class LOAD extends LispFunction {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("could not load ''{0}''", fileName);
|
||||
return format("could not load ''{0}''", fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
package function.builtin;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
import static table.FunctionTable.lookupFunction;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
import function.*;
|
||||
import sexpression.*;
|
||||
|
@ -38,7 +37,7 @@ public class SYMBOL_FUNCTION extends LispFunction {
|
|||
|
||||
String typeIndicator = function instanceof LispSpecialFunction ? "SPECIAL-FUNCTION" : "FUNCTION";
|
||||
|
||||
return new Symbol(MessageFormat.format("#<{0} {1}>", typeIndicator, symbol));
|
||||
return new Symbol(format("#<{0} {1}>", typeIndicator, symbol));
|
||||
}
|
||||
|
||||
public static class UndefinedSymbolFunctionException extends LispException {
|
||||
|
@ -52,7 +51,7 @@ public class SYMBOL_FUNCTION extends LispFunction {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("SYMBOL-FUNCTION: undefined function: {0}", function);
|
||||
return format("SYMBOL-FUNCTION: undefined function: {0}", function);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package function.builtin.special;
|
||||
|
||||
import static function.builtin.cons.LIST.makeList;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static table.FunctionTable.*;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import environment.RuntimeEnvironment;
|
||||
import error.LispWarning;
|
||||
import function.*;
|
||||
|
@ -67,7 +66,7 @@ public abstract class Define extends LispSpecialFunction {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("redefining function {0}", functionName);
|
||||
return format("redefining function {0}", functionName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package interpreter;
|
|||
|
||||
public class InteractiveLispInterpreter extends LispInterpreter {
|
||||
|
||||
private static final String PROMPT = "~ ";
|
||||
public static final String PROMPT = "~ ";
|
||||
|
||||
@Override
|
||||
protected void prompt() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package main;
|
||||
|
||||
import static com.googlecode.lanterna.terminal.IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter;
|
||||
import static terminal.LispTerminal.END_OF_SEGMENT;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -8,7 +9,6 @@ import java.util.function.Function;
|
|||
import com.googlecode.lanterna.terminal.*;
|
||||
|
||||
import interpreter.*;
|
||||
import stream.SafeOutputStream;
|
||||
import terminal.LispTerminal;
|
||||
|
||||
public class LispMain {
|
||||
|
@ -30,58 +30,76 @@ public class LispMain {
|
|||
lispMain.runWithFile(arguments[0]);
|
||||
}
|
||||
|
||||
private LispInterpreterBuilder builder;
|
||||
private PipedInputStream inputReader;
|
||||
private PipedOutputStream inputWriter;
|
||||
private PipedInputStream outputReader;
|
||||
private PipedOutputStream outputWriter;
|
||||
private PrintStream outputStream;
|
||||
private SafeOutputStream safeOutputWriter;
|
||||
private PrintStream output;
|
||||
private LispTerminal lispTerminal;
|
||||
|
||||
private void runInteractive() {
|
||||
initializeTerminalAndStreams();
|
||||
printGreeting();
|
||||
lispTerminal.start();
|
||||
buildInteractiveInterpreter().interpret();
|
||||
outputStream.close();
|
||||
public LispMain() {
|
||||
this.builder = LispInterpreterBuilderImpl.getInstance();
|
||||
|
||||
TerminalConfiguration terminalConfiguration = new TerminalConfiguration();
|
||||
terminalConfiguration.setInputWriter(new PipedOutputStream());
|
||||
terminalConfiguration.setOutputReader(new PipedInputStream());
|
||||
terminalConfiguration.setTerminal(createIOSafeTerminal());
|
||||
|
||||
initializeTerminal(terminalConfiguration);
|
||||
}
|
||||
|
||||
private void initializeTerminalAndStreams() {
|
||||
private IOSafeTerminal createIOSafeTerminal() {
|
||||
return createRuntimeExceptionConvertingAdapter(createDefaultTerminal());
|
||||
}
|
||||
|
||||
private Terminal createDefaultTerminal() {
|
||||
try {
|
||||
initalizeTerminalAndStreamsWithException();
|
||||
return new DefaultTerminalFactory().createTerminal();
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initalizeTerminalAndStreamsWithException() throws IOException {
|
||||
inputReader = new PipedInputStream();
|
||||
inputWriter = new PipedOutputStream(inputReader);
|
||||
outputReader = new PipedInputStream();
|
||||
outputWriter = new PipedOutputStream(outputReader);
|
||||
outputStream = new PrintStream(outputWriter);
|
||||
safeOutputWriter = new SafeOutputStream(outputWriter);
|
||||
lispTerminal = new LispTerminal(createIOSafeTerminal(), inputWriter, outputReader);
|
||||
public LispMain(LispInterpreterBuilder builder, TerminalConfiguration configuration) {
|
||||
this.builder = builder;
|
||||
initializeTerminal(configuration);
|
||||
}
|
||||
|
||||
private IOSafeTerminal createIOSafeTerminal() throws IOException {
|
||||
Terminal defaultTerminal = new DefaultTerminalFactory().createTerminal();
|
||||
private void initializeTerminal(TerminalConfiguration configuration) {
|
||||
try {
|
||||
initalizeTerminalWithException(configuration);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
return IOSafeTerminalAdapter.createRuntimeExceptionConvertingAdapter(defaultTerminal);
|
||||
private void initalizeTerminalWithException(TerminalConfiguration configuration) throws IOException {
|
||||
PipedOutputStream inputWriter = configuration.getInputWriter();
|
||||
PipedInputStream outputReader = configuration.getOutputReader();
|
||||
|
||||
inputReader = new PipedInputStream(inputWriter);
|
||||
outputWriter = new PipedOutputStream(outputReader);
|
||||
output = new PrintStream(outputWriter);
|
||||
lispTerminal = new LispTerminal(configuration.getTerminal(), inputWriter, outputReader);
|
||||
}
|
||||
|
||||
public void runInteractive() {
|
||||
printGreeting();
|
||||
lispTerminal.start();
|
||||
buildInteractiveInterpreter().interpret();
|
||||
shutdownTerminal();
|
||||
}
|
||||
|
||||
private void printGreeting() {
|
||||
outputStream.println(GREETING);
|
||||
outputStream.println();
|
||||
output.println(GREETING);
|
||||
output.println();
|
||||
}
|
||||
|
||||
private LispInterpreter buildInteractiveInterpreter() {
|
||||
LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance();
|
||||
builder.setInput(inputReader, "terminal");
|
||||
builder.setOutput(outputStream);
|
||||
builder.setErrorOutput(outputStream);
|
||||
builder.setTerminationFunction(this::shutdown);
|
||||
builder.setErrorTerminationFunction(this::shutdown);
|
||||
builder.setOutput(output);
|
||||
builder.setErrorOutput(output);
|
||||
builder.setTerminationFunction(this::shutdownTerminal);
|
||||
builder.setErrorTerminationFunction(this::shutdownTerminal);
|
||||
builder.setPromptDecorator(s -> s + END_OF_SEGMENT);
|
||||
builder.setValueOutputDecorator(makeColorDecorator(ANSI_GREEN));
|
||||
builder.setWarningOutputDecorator(makeColorDecorator(ANSI_YELLOW));
|
||||
|
@ -91,11 +109,10 @@ public class LispMain {
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
private void shutdown() {
|
||||
outputStream.println();
|
||||
outputStream.println(END_OF_SEGMENT);
|
||||
private void shutdownTerminal() {
|
||||
output.print(END_OF_SEGMENT);
|
||||
lispTerminal.stop();
|
||||
safeOutputWriter.close();
|
||||
output.close();
|
||||
}
|
||||
|
||||
private Function<String, String> makeColorDecorator(String color) {
|
||||
|
@ -108,12 +125,11 @@ public class LispMain {
|
|||
};
|
||||
}
|
||||
|
||||
private void runWithFile(String fileName) {
|
||||
public void runWithFile(String fileName) {
|
||||
buildFileInterpreter(fileName).interpret();
|
||||
}
|
||||
|
||||
private LispInterpreter buildFileInterpreter(String fileName) {
|
||||
LispInterpreterBuilder builder = LispInterpreterBuilderImpl.getInstance();
|
||||
builder.useFile(fileName);
|
||||
builder.setOutput(System.out);
|
||||
builder.setErrorOutput(System.err);
|
||||
|
@ -126,4 +142,36 @@ public class LispMain {
|
|||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public class TerminalConfiguration {
|
||||
|
||||
private PipedOutputStream inputWriter;
|
||||
private PipedInputStream outputReader;
|
||||
private IOSafeTerminal terminal;
|
||||
|
||||
public PipedOutputStream getInputWriter() {
|
||||
return inputWriter;
|
||||
}
|
||||
|
||||
public void setInputWriter(PipedOutputStream inputWriter) {
|
||||
this.inputWriter = inputWriter;
|
||||
}
|
||||
|
||||
public PipedInputStream getOutputReader() {
|
||||
return outputReader;
|
||||
}
|
||||
|
||||
public void setOutputReader(PipedInputStream outputReader) {
|
||||
this.outputReader = outputReader;
|
||||
}
|
||||
|
||||
public IOSafeTerminal getTerminal() {
|
||||
return terminal;
|
||||
}
|
||||
|
||||
public void setTerminal(IOSafeTerminal terminal) {
|
||||
this.terminal = terminal;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
package sexpression;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import error.LispException;
|
||||
|
||||
|
@ -49,7 +50,7 @@ public class LispNumber extends Atom {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("{0} is not a valid integer", text);
|
||||
return format("{0} is not a valid integer", text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package table;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import error.CriticalLispException;
|
||||
|
@ -141,7 +142,7 @@ public class FunctionTable {
|
|||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return MessageFormat.format("Could not create an instance of ''{0}''", functionName);
|
||||
return format("Could not create an instance of ''{0}''", functionName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package terminal;
|
||||
|
||||
import static java.lang.Character.isDigit;
|
||||
import static terminal.ControlSequenceLookup.lookupControlSequence;
|
||||
import static util.Characters.*;
|
||||
|
||||
import stream.SafeInputStream;
|
||||
|
@ -12,14 +11,13 @@ class ControlSequenceHandler {
|
|||
return c == UNICODE_ESCAPE;
|
||||
}
|
||||
|
||||
private ControlSequenceLookup controlSequenceLookup;
|
||||
private SafeInputStream input;
|
||||
private String code;
|
||||
private int currentCharacter;
|
||||
|
||||
public ControlSequenceHandler() {
|
||||
this.input = null;
|
||||
this.code = "";
|
||||
this.currentCharacter = 0;
|
||||
this.controlSequenceLookup = new ControlSequenceLookup();
|
||||
}
|
||||
|
||||
public ControlSequence parse(SafeInputStream inputStream) {
|
||||
|
@ -30,7 +28,7 @@ class ControlSequenceHandler {
|
|||
if (isExpectedFirstCharacter())
|
||||
readCode();
|
||||
|
||||
return lookupControlSequence((char) currentCharacter, code);
|
||||
return controlSequenceLookup.get((char) currentCharacter, code);
|
||||
}
|
||||
|
||||
private void readCharacter() {
|
||||
|
|
|
@ -8,9 +8,15 @@ import terminal.ControlSequence.NullControlSequence;
|
|||
|
||||
public class ControlSequenceLookup {
|
||||
|
||||
private static Map<Character, Map<String, ControlSequence>> commands = new HashMap<>();
|
||||
private Map<Character, Map<String, ControlSequence>> commands;
|
||||
|
||||
static {
|
||||
public ControlSequenceLookup() {
|
||||
this.commands = new HashMap<>();
|
||||
|
||||
initializeCommands();
|
||||
}
|
||||
|
||||
private void initializeCommands() {
|
||||
Map<String, ControlSequence> sgrCodes = new HashMap<>();
|
||||
|
||||
for (SelectGraphicRendition sgr : SelectGraphicRendition.values())
|
||||
|
@ -19,7 +25,7 @@ public class ControlSequenceLookup {
|
|||
commands.put(SGR_COMMAND, sgrCodes);
|
||||
}
|
||||
|
||||
public static ControlSequence lookupControlSequence(char command, String code) {
|
||||
public ControlSequence get(char command, String code) {
|
||||
Map<String, ControlSequence> codes = commands.getOrDefault(command, new HashMap<>());
|
||||
|
||||
return codes.getOrDefault(code, new NullControlSequence());
|
||||
|
|
|
@ -115,13 +115,6 @@ public class LispTerminal {
|
|||
return keyStroke;
|
||||
}
|
||||
|
||||
private void doControlC() {
|
||||
moveCursorToEndOfInput();
|
||||
terminal.putCharacter('\n');
|
||||
setOriginToCurrentPosition();
|
||||
stop();
|
||||
}
|
||||
|
||||
private synchronized void handleKey(KeyStroke keyStroke) {
|
||||
doKey(keyStroke);
|
||||
terminal.flush();
|
||||
|
@ -142,10 +135,20 @@ public class LispTerminal {
|
|||
}
|
||||
|
||||
private synchronized void doControlCharacter(KeyStroke keyStroke) {
|
||||
if (keyStroke.getCharacter() == 'd')
|
||||
if (keyStroke.getCharacter() == 'c')
|
||||
doControlC();
|
||||
else if (keyStroke.getCharacter() == 'd')
|
||||
doControlD();
|
||||
}
|
||||
|
||||
private void doControlC() {
|
||||
moveCursorToEndOfInput();
|
||||
terminal.putCharacter('\n');
|
||||
inputLine = "";
|
||||
setOriginToCurrentPosition();
|
||||
stop();
|
||||
}
|
||||
|
||||
private synchronized void doControlD() {
|
||||
doEnter();
|
||||
stop();
|
||||
|
@ -374,7 +377,7 @@ public class LispTerminal {
|
|||
}
|
||||
|
||||
private synchronized void putOutputToTerminal() {
|
||||
SafeInputStream input = new SafeInputStream(new ByteArrayInputStream(outputSegment.getBytes()));
|
||||
SafeInputStream input = convertOutputToStream();
|
||||
|
||||
for (int c = input.read(); c != EOF; c = input.read())
|
||||
if (isEscape((char) c))
|
||||
|
@ -383,6 +386,10 @@ public class LispTerminal {
|
|||
terminal.putCharacter((char) c);
|
||||
}
|
||||
|
||||
private synchronized SafeInputStream convertOutputToStream() {
|
||||
return new SafeInputStream(new ByteArrayInputStream(outputSegment.getBytes()));
|
||||
}
|
||||
|
||||
private void applyControlSequence(SafeInputStream input) {
|
||||
ControlSequence controlSequence = controlSequenceHandler.parse(input);
|
||||
controlSequence.applyTo(terminal);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package token;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import static java.text.MessageFormat.format;
|
||||
|
||||
import error.*;
|
||||
import file.FilePosition;
|
||||
|
@ -37,7 +37,7 @@ public interface TokenFactory {
|
|||
|
||||
@Override
|
||||
public String getMessagePrefix() {
|
||||
return MessageFormat.format("illegal character >>{0}<<", text);
|
||||
return format("illegal character >>{0}<<", text);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -152,10 +152,9 @@ public class ErrorManagerTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void severityCoverage() {
|
||||
Severity.valueOf(WARNING.toString());
|
||||
Severity.valueOf(ERROR.toString());
|
||||
Severity.valueOf(CRITICAL.toString());
|
||||
public void severityEnumCoverage() {
|
||||
for (Severity severity : Severity.values())
|
||||
Severity.valueOf(severity.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package function.builtin;
|
||||
|
||||
import static java.text.MessageFormat.format;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static testutil.TestUtilities.evaluateString;
|
||||
|
||||
import java.io.*;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
|
@ -40,16 +40,16 @@ public class PRINTTest {
|
|||
public void printStringWorks() {
|
||||
String output = "\"Hello, world!\"";
|
||||
|
||||
evaluateString(MessageFormat.format("(print {0})", output));
|
||||
assertPrinted(MessageFormat.format("{0}\n", output));
|
||||
evaluateString(format("(print {0})", output));
|
||||
assertPrinted(format("{0}\n", output));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void printSymbolWorks() {
|
||||
String output = "A";
|
||||
|
||||
evaluateString(MessageFormat.format("(print ''{0})", output));
|
||||
assertPrinted(MessageFormat.format("{0}\n", output));
|
||||
evaluateString(format("(print ''{0})", output));
|
||||
assertPrinted(format("{0}\n", output));
|
||||
}
|
||||
|
||||
@Test(expected = TooManyArgumentsException.class)
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package interpreter;
|
||||
|
||||
import static error.ErrorManager.Severity.CRITICAL;
|
||||
import static interpreter.InteractiveLispInterpreter.PROMPT;
|
||||
import static java.text.MessageFormat.format;
|
||||
import static org.junit.Assert.*;
|
||||
import static testutil.TestUtilities.createInputStreamFromString;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
@ -11,7 +14,7 @@ import org.junit.*;
|
|||
import environment.RuntimeEnvironment;
|
||||
import interpreter.LispInterpreterBuilderImpl.InterpreterAlreadyBuiltException;
|
||||
|
||||
public class LispInterpreterBuilderTest {
|
||||
public class LispInterpreterTest {
|
||||
|
||||
private static final String TERMINATED = "terminated";
|
||||
|
||||
|
@ -21,7 +24,7 @@ public class LispInterpreterBuilderTest {
|
|||
private RuntimeEnvironment environment;
|
||||
private LispInterpreterBuilder builder;
|
||||
|
||||
public LispInterpreterBuilderTest() {
|
||||
public LispInterpreterTest() {
|
||||
this.environment = RuntimeEnvironment.getInstance();
|
||||
|
||||
this.builder = new LispInterpreterBuilderImpl() {
|
||||
|
@ -68,6 +71,7 @@ public class LispInterpreterBuilderTest {
|
|||
setCommonFeatures();
|
||||
builder.setInput(System.in, "stdin");
|
||||
LispInterpreter interpreter = builder.build();
|
||||
|
||||
assertTrue(interpreter instanceof InteractiveLispInterpreter);
|
||||
}
|
||||
|
||||
|
@ -77,6 +81,7 @@ public class LispInterpreterBuilderTest {
|
|||
builder.setInput(System.in, "stdin");
|
||||
builder.setNotInteractive();
|
||||
LispInterpreter interpreter = builder.build();
|
||||
|
||||
assertFalse(interpreter instanceof InteractiveLispInterpreter);
|
||||
assertFalse(interpreter instanceof FileLispInterpreter);
|
||||
}
|
||||
|
@ -86,6 +91,7 @@ public class LispInterpreterBuilderTest {
|
|||
setCommonFeatures();
|
||||
builder.useFile("test/interpreter/test-files/file.lisp");
|
||||
LispInterpreter interpreter = builder.build();
|
||||
|
||||
assertTrue(interpreter instanceof FileLispInterpreter);
|
||||
}
|
||||
|
||||
|
@ -98,6 +104,7 @@ public class LispInterpreterBuilderTest {
|
|||
@Test
|
||||
public void interpreterAlreadyBuiltException_HasCorrectAttributes() {
|
||||
InterpreterAlreadyBuiltException e = new InterpreterAlreadyBuiltException();
|
||||
|
||||
assertEquals(CRITICAL, e.getSeverity());
|
||||
assertNotNull(e.getMessage());
|
||||
assertTrue(e.getMessage().length() > 0);
|
||||
|
@ -117,6 +124,7 @@ public class LispInterpreterBuilderTest {
|
|||
setCommonFeatures();
|
||||
builder.useFile("test/interpreter/test-files/does-not-exist.lisp");
|
||||
builder.build();
|
||||
|
||||
assertErrorMessageWritten();
|
||||
assertTerminated();
|
||||
}
|
||||
|
@ -124,6 +132,7 @@ public class LispInterpreterBuilderTest {
|
|||
@Test
|
||||
public void makeSureDecoratorsAreInitializedWithDefaults() {
|
||||
builder.build();
|
||||
|
||||
assertEquals("", environment.decoratePrompt(""));
|
||||
assertEquals("", environment.decorateValueOutput(""));
|
||||
assertEquals("", environment.decorateWarningOutput(""));
|
||||
|
@ -139,6 +148,7 @@ public class LispInterpreterBuilderTest {
|
|||
builder.setErrorOutputDecorator(s -> "*" + s + "*");
|
||||
builder.setCriticalOutputDecorator(s -> "$" + s + "$");
|
||||
builder.build();
|
||||
|
||||
assertEquals("#x#", environment.decoratePrompt("x"));
|
||||
assertEquals("@x@", environment.decorateValueOutput("x"));
|
||||
assertEquals("%x%", environment.decorateWarningOutput("x"));
|
||||
|
@ -146,4 +156,35 @@ public class LispInterpreterBuilderTest {
|
|||
assertEquals("$x$", environment.decorateCriticalOutput("x"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileBasedInterpreterWorks() {
|
||||
setCommonFeatures();
|
||||
builder.useFile("test/interpreter/test-files/file.lisp");
|
||||
builder.build().interpret();
|
||||
|
||||
assertEquals("PICKLE\n\n", outputStream.toString());
|
||||
assertEquals("", errorOutputStream.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interactiveInterpreterWorks() {
|
||||
setCommonFeatures();
|
||||
builder.setInput(createInputStreamFromString("'pickle"), "input");
|
||||
builder.build().interpret();
|
||||
|
||||
assertEquals(format("{0}\n{1}\n{0}\n\n", PROMPT, "PICKLE"), outputStream.toString());
|
||||
assertEquals("", errorOutputStream.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpreterHandlesError() {
|
||||
setCommonFeatures();
|
||||
builder.setNotInteractive();
|
||||
builder.setInput(createInputStreamFromString("pickle"), "input");
|
||||
builder.build().interpret();
|
||||
|
||||
assertEquals("\n", outputStream.toString());
|
||||
assertEquals("[error] symbol PICKLE has no value\n", errorOutputStream.toString());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
'pickle
|
|
@ -0,0 +1,43 @@
|
|||
package stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static testutil.TestUtilities.*;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class SafeInputStreamTest {
|
||||
|
||||
SafeInputStream safe;
|
||||
SafeInputStream safeWithException;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
safe = new SafeInputStream(createInputStreamFromString("a"));
|
||||
safeWithException = new SafeInputStream(createIOExceptionThrowingInputStream());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {}
|
||||
|
||||
@Test
|
||||
public void readWorks() {
|
||||
assertEquals('a', (char) safe.read());
|
||||
assertEquals(-1, safe.read());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeWorks() {
|
||||
safe.close();
|
||||
}
|
||||
|
||||
@Test(expected = UncheckedIOException.class)
|
||||
public void readThrowsUncheckedException() {
|
||||
safeWithException.read();
|
||||
}
|
||||
|
||||
@Test(expected = UncheckedIOException.class)
|
||||
public void closeThrowsUncheckedException() {
|
||||
safeWithException.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package stream;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static testutil.TestUtilities.createIOExceptionThrowingOutputStream;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import org.junit.*;
|
||||
|
||||
public class SafeOutputStreamTest {
|
||||
|
||||
SafeOutputStream safe;
|
||||
SafeOutputStream safeWithException;
|
||||
ByteArrayOutputStream output;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
output = new ByteArrayOutputStream();
|
||||
safe = new SafeOutputStream(output);
|
||||
safeWithException = new SafeOutputStream(createIOExceptionThrowingOutputStream());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void writeWorks() {
|
||||
safe.write("write".getBytes());
|
||||
assertEquals("write", output.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void flushWorks() {
|
||||
safe.flush();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void closeWorks() {
|
||||
safe.close();
|
||||
}
|
||||
|
||||
@Test(expected = UncheckedIOException.class)
|
||||
public void writeThrowsUncheckedException() {
|
||||
safeWithException.write("write".getBytes());
|
||||
}
|
||||
|
||||
@Test(expected = UncheckedIOException.class)
|
||||
public void flushThrowsUncheckedException() {
|
||||
safeWithException.flush();
|
||||
}
|
||||
|
||||
@Test(expected = UncheckedIOException.class)
|
||||
public void closeThrowsUncheckedException() {
|
||||
safeWithException.close();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package terminal;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
import static terminal.SelectGraphicRendition.*;
|
||||
|
||||
import java.util.*;
|
||||
|
@ -79,4 +79,16 @@ public class ControlSequenceTest {
|
|||
assertTrue(indicatorSet.contains("MAGENTA"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullControlSequenceHasCorrectCode() {
|
||||
ControlSequence nullControlSequence = new NullControlSequence();
|
||||
assertEquals("", nullControlSequence.getCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SelectGraphicRenditionEnumCoverage() {
|
||||
for (SelectGraphicRendition sgr : SelectGraphicRendition.values())
|
||||
SelectGraphicRendition.valueOf(sgr.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -347,6 +347,17 @@ public class LispTerminalTest {
|
|||
assertInputWritten("control-d\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controlCWorks() {
|
||||
enterCharacters("ctrl-c");
|
||||
enterControlCharacter('c');
|
||||
produceOutput("");
|
||||
assertInputStreamClosed();
|
||||
assertInputWritten("");
|
||||
assertCharacterPositions(new char[][] { { 'c', 't', 'r', 'l', '-', 'c', ' ', ' ', ' ' },
|
||||
{ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' } });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void controlDWorksInMiddleOfInput() {
|
||||
enterCharacters("control-d");
|
||||
|
|
|
@ -23,7 +23,37 @@ public final class TestUtilities {
|
|||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
throw new IOException("test IOException");
|
||||
throw new IOException("read()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
throw new IOException("close()");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static OutputStream createIOExceptionThrowingOutputStream() {
|
||||
return new OutputStream() {
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
throw new IOException("write(byte[])");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
throw new IOException("flush()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
throw new IOException("close()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int arg0) throws IOException {
|
||||
throw new IOException("write(int)");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue