package function.builtin.special; import static org.junit.Assert.assertEquals; import static testutil.TestUtilities.*; import java.io.*; import org.junit.*; import environment.Environment; import function.ArgumentValidator.*; import table.FunctionTable; public class DEFUNTester { private ByteArrayOutputStream outputStream; private void assertPrinted(String expected) { assertEquals(expected, outputStream.toString()); } @Before public void setUp() { this.outputStream = new ByteArrayOutputStream(); Environment.getInstance().setOutput(new PrintStream(outputStream)); 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 redefineFunction_DisplaysWarning() { String input = "(defun myFunction () nil)"; evaluateString(input); evaluateString(input); assertPrinted("WARNING: redefining function MYFUNCTION\n"); } @Test public void redefineFunction_ActuallyRedefinesFunction() { evaluateString("(defun myFunction2 () nil)"); evaluateString("(defun myFunction2 () T)"); assertPrinted("WARNING: redefining function MYFUNCTION2\n"); assertSExpressionsMatch(parseString("t"), evaluateString("(myFunction2)")); } @Test(expected = DottedArgumentListException.class) public void testDefunWithDottedLambdaList() { String input = "(funcall 'defun 'x (cons 'a 'b) ())"; evaluateString(input); } @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)"); } }