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