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 table.FunctionTable; public class DEFUNTester { private ByteArrayOutputStream outputStream; private RuntimeEnvironment environment; public DEFUNTester() { 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 testDefun() { String input = "(defun f () t)"; assertSExpressionsMatch(parseString("f"), evaluateString(input)); assertSExpressionsMatch(parseString("t"), evaluateString("(f)")); } @Test public void testDefunWithEmptyBody() { String input = "(defun f ())"; assertSExpressionsMatch(parseString("f"), evaluateString(input)); assertSExpressionsMatch(parseString("()"), evaluateString("(f)")); } @Test public void testDefunEvaluatesArguments() { evaluateString("(defun f (x) (car x))"); assertSExpressionsMatch(parseString("1"), evaluateString("(f '(1 2 3))")); } @Test public void redefineFunction_DisplaysWarning() { String input = "(defun myFunction () nil)"; evaluateString(input); evaluateString(input); assertSomethingPrinted(); } @Test public void redefineFunction_ActuallyRedefinesFunction() { evaluateString("(defun myFunction2 () nil)"); evaluateString("(defun myFunction2 () T)"); assertSomethingPrinted(); assertSExpressionsMatch(parseString("t"), evaluateString("(myFunction2)")); } @Test(expected = DottedArgumentListException.class) public void testDefunWithDottedLambdaList() { evaluateString("(funcall 'defun 'x (cons 'a 'b) ())"); } @Test(expected = BadArgumentTypeException.class) public void testDefunWithNonSymbolName() { evaluateString("(defun 1 () ())"); } @Test(expected = BadArgumentTypeException.class) public void testDefunWithBadLambdaList() { evaluateString("(defun x a ())"); } @Test(expected = TooFewArgumentsException.class) public void testDefunWithTooFewArguments() { evaluateString("(defun x)"); } }