Mike Cifelli
64e18fe076
Added unit tests and cleaned up some code The setup for acceptance tests now cleans up the environment
177 lines
5.4 KiB
Java
177 lines
5.4 KiB
Java
package function.builtin.special;
|
|
|
|
import static org.junit.Assert.assertTrue;
|
|
import static testutil.TestUtilities.*;
|
|
|
|
import java.io.*;
|
|
|
|
import org.junit.*;
|
|
|
|
import environment.RuntimeEnvironment;
|
|
import error.ErrorManager;
|
|
import function.ArgumentValidator.*;
|
|
import function.UserDefinedFunction.IllegalKeywordRestPositionException;
|
|
import table.FunctionTable;
|
|
|
|
public class DEFINE_MACROTester {
|
|
|
|
private ByteArrayOutputStream outputStream;
|
|
private RuntimeEnvironment environment;
|
|
|
|
public DEFINE_MACROTester() {
|
|
this.environment = RuntimeEnvironment.getInstance();
|
|
}
|
|
|
|
private void assertSomethingPrinted() {
|
|
assertTrue(outputStream.toByteArray().length > 0);
|
|
}
|
|
|
|
@Before
|
|
public void setUp() {
|
|
outputStream = new ByteArrayOutputStream();
|
|
|
|
environment.setOutput(new PrintStream(outputStream));
|
|
environment.setErrorManager(new ErrorManager());
|
|
environment.setWarningOutputDecorator(s -> s);
|
|
|
|
FunctionTable.reset();
|
|
}
|
|
|
|
@After
|
|
public void tearDown() {
|
|
FunctionTable.reset();
|
|
}
|
|
|
|
@Test
|
|
public void defineMacro() {
|
|
String input = "(define-macro f () t)";
|
|
|
|
assertSExpressionsMatch(parseString("f"), evaluateString(input));
|
|
assertSExpressionsMatch(parseString("t"), evaluateString("(f)"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroWithEmptyBody() {
|
|
String input = "(define-macro f ())";
|
|
|
|
assertSExpressionsMatch(parseString("f"), evaluateString(input));
|
|
assertSExpressionsMatch(parseString("()"), evaluateString("(f)"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroDoesNotEvaluatesArguments() {
|
|
evaluateString("(define-macro f (x) (car x))");
|
|
assertSExpressionsMatch(parseString("quote"), evaluateString("(f '(1 2 3))"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroAdd() {
|
|
evaluateString("(define-macro f (x) (+ (eval x) 23))");
|
|
assertSExpressionsMatch(parseString("27"), evaluateString("(f (+ 2 2))"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroSetVariable() {
|
|
evaluateString("(define-macro f (x) (set x 23))");
|
|
evaluateString("(f y)");
|
|
assertSExpressionsMatch(parseString("23"), evaluateString("y"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroVariableCapture() {
|
|
evaluateString("(setf x 0)");
|
|
evaluateString("(define-macro f (x) (set x 23))");
|
|
evaluateString("(f x)");
|
|
assertSExpressionsMatch(parseString("0"), evaluateString("x"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroAvoidVariableCaptureConvention() {
|
|
evaluateString("(setf x 0)");
|
|
evaluateString("(define-macro f (-x-) (set -x- 23))");
|
|
evaluateString("(f x)");
|
|
assertSExpressionsMatch(parseString("23"), evaluateString("x"));
|
|
}
|
|
|
|
@Test
|
|
public void redefineMacro_DisplaysWarning() {
|
|
String input = "(define-macro myFunction () nil)";
|
|
evaluateString(input);
|
|
evaluateString(input);
|
|
|
|
assertSomethingPrinted();
|
|
}
|
|
|
|
@Test
|
|
public void redefineMacro_ActuallyRedefinesMacro() {
|
|
evaluateString("(define-macro myMacro () nil)");
|
|
evaluateString("(define-macro myMacro () T)");
|
|
|
|
assertSomethingPrinted();
|
|
assertSExpressionsMatch(parseString("t"), evaluateString("(myMacro)"));
|
|
}
|
|
|
|
@Test(expected = DottedArgumentListException.class)
|
|
public void defineMacroWithDottedLambdaList() {
|
|
evaluateString("(funcall 'define-macro 'x (cons 'a 'b) ())");
|
|
}
|
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
|
public void defineMacroWithNonSymbolName() {
|
|
evaluateString("(define-macro 1 () ())");
|
|
}
|
|
|
|
@Test(expected = BadArgumentTypeException.class)
|
|
public void defineMacroWithBadLambdaList() {
|
|
evaluateString("(define-macro x a ())");
|
|
}
|
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
|
public void defineMacroWithTooFewArguments() {
|
|
evaluateString("(define-macro x)");
|
|
}
|
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
|
public void defineMacroAndCallWithTooFewArguments() {
|
|
evaluateString("(define-macro x (a b))");
|
|
evaluateString("(x a)");
|
|
}
|
|
|
|
@Test(expected = TooManyArgumentsException.class)
|
|
public void defineMacroAndCallWithTooManyArguments() {
|
|
evaluateString("(define-macro x (a b))");
|
|
evaluateString("(x a b c)");
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroWithKeywordRestParameter() {
|
|
evaluateString("(define-macro f (&rest x) (car x))");
|
|
assertSExpressionsMatch(parseString("1"), evaluateString("(f 1 2 3 4 5)"));
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroWithNormalAndKeywordRestParameter() {
|
|
evaluateString("(define-macro f (a &rest b) (cons a b))");
|
|
assertSExpressionsMatch(parseString("(1 2 3 4 5)"), evaluateString("(f 1 2 3 4 5)"));
|
|
}
|
|
|
|
@Test(expected = IllegalKeywordRestPositionException.class)
|
|
public void defineMacroWithParametersFollowingKeywordRest() {
|
|
evaluateString("(define-macro f (a &rest b c) (cons a b))");
|
|
evaluateString("(f 1 2 3)");
|
|
}
|
|
|
|
@Test
|
|
public void defineMacroWithKeywordRest_CallWithNoArguments() {
|
|
evaluateString("(define-macro f (&rest a) (car a))");
|
|
assertSExpressionsMatch(parseString("nil"), evaluateString("(f)"));
|
|
}
|
|
|
|
@Test(expected = TooFewArgumentsException.class)
|
|
public void defineMacroWithNormalAndKeywordRest_CallWithNoArguments() {
|
|
evaluateString("(define-macro f (a &rest b) a)");
|
|
evaluateString("(f)");
|
|
}
|
|
|
|
}
|