package table;

import static org.junit.Assert.*;

import org.junit.*;

import sexpression.*;

public class ExecutionContextTester {

    private ExecutionContext executionContext;

    public ExecutionContextTester() {
        this.executionContext = ExecutionContext.getInstance();
    }

    @Before
    public void setUp() {
        executionContext.clearContext();
    }

    @After
    public void tearDown() {
        executionContext.clearContext();
    }

    @Test
    public void assignANewScope() {
        SymbolTable scope = new SymbolTable();
        executionContext.setScope(scope);

        assertEquals(scope, executionContext.getScope());
    }

    @Test
    public void clearContext() {
        SymbolTable scope = new SymbolTable();
        executionContext.setScope(scope);

        assertEquals(scope, executionContext.getScope());
        executionContext.clearContext();
        assertNotEquals(scope, executionContext.getScope());
        assertNull(executionContext.getScope().getParent());
    }

    @Test
    public void lookupVariable() {
        executionContext.getScope().put("test", Symbol.T);

        assertEquals(Symbol.T, executionContext.lookupSymbolValue("test"));
    }

    @Test
    public void lookupLocalVariable() {
        SymbolTable scope = new SymbolTable(executionContext.getScope());

        scope.put("local", Symbol.T);
        executionContext.setScope(scope);

        assertEquals(Symbol.T, executionContext.lookupSymbolValue("local"));
    }

    @Test
    public void lookupGlobalVariable() {
        SymbolTable scope = new SymbolTable(executionContext.getScope());

        executionContext.getScope().put("global", Symbol.T);
        executionContext.setScope(scope);

        assertEquals(Symbol.T, executionContext.lookupSymbolValue("global"));
    }

    @Test
    public void lookupShadowedVariable() {
        SymbolTable scope = new SymbolTable(executionContext.getScope());

        scope.put("shadowed", Nil.getInstance());
        executionContext.getScope().put("shadowed", Symbol.T);
        executionContext.setScope(scope);

        assertEquals(Nil.getInstance(), executionContext.lookupSymbolValue("shadowed"));
    }

}
