package function.builtin.special; import static org.junit.Assert.assertNull; import static testutil.TestUtilities.*; import org.junit.*; import function.ArgumentValidator.*; import function.builtin.EVAL.UndefinedSymbolException; import sexpression.LispNumber; import table.*; public class SETFTester { private ExecutionContext executionContext; public SETFTester() { this.executionContext = ExecutionContext.getInstance(); } @Before public void setUp() { executionContext.clearContext(); } @Test public void testSetf() { evaluateString("(setf a 23)"); assertSExpressionsMatch(new LispNumber("23"), evaluateString("a")); } @Test public void lookupDefinedSymbol() { evaluateString("(setf a 23)"); assertSExpressionsMatch(new LispNumber("23"), executionContext.lookupSymbolValue("A")); } @Test public void lookupUndefinedSymbol() { assertNull(executionContext.lookupSymbolValue("A")); } @Test public void setfGlobalVariable() { evaluateString("(setf a 23)"); SymbolTable global = executionContext.getScope(); executionContext.setScope(new SymbolTable(global)); evaluateString("(setf a 94)"); executionContext.setScope(global); assertSExpressionsMatch(new LispNumber("94"), evaluateString("a")); } @Test(expected = UndefinedSymbolException.class) public void setfLocalVariableDefined_DoesNotSetGlobal() { SymbolTable global = executionContext.getScope(); SymbolTable local = new SymbolTable(global); local.put("A", new LispNumber("99")); executionContext.setScope(local); evaluateString("(setf a 94)"); executionContext.setScope(global); evaluateString("a"); } @Test public void setfLocalVariableUndefined_SetsGlobal() { SymbolTable global = executionContext.getScope(); SymbolTable local = new SymbolTable(global); executionContext.setScope(local); evaluateString("(setf a 94)"); executionContext.setScope(global); assertSExpressionsMatch(new LispNumber("94"), evaluateString("a")); } @Test(expected = BadArgumentTypeException.class) public void testSetfWithNonSymbol() { evaluateString("(setf 1 2)"); } @Test(expected = TooFewArgumentsException.class) public void testSetfWithTooFewArguments() { evaluateString("(setf x)"); } @Test(expected = TooManyArgumentsException.class) public void testSetfWithTooManyArguments() { evaluateString("(setf a b c)"); } }