package function.builtin.special;

import static testutil.TestUtilities.*;
import static testutil.TypeAssertions.*;

import org.junit.*;

import function.builtin.EVAL.UndefinedSymbolException;
import sexpression.LispNumber;
import table.ExecutionContext;

public class ANDTest {

    private ExecutionContext executionContext;

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

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

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

    @Test
    public void andByItself() {
        String input = "(and)";

        assertT(evaluateString(input));
    }

    @Test
    public void andWithNil() {
        String input = "(and nil)";

        assertNil(evaluateString(input));
    }

    @Test
    public void andWithT() {
        String input = "(and t)";

        assertT(evaluateString(input));
    }

    @Test
    public void andWithNumber() {
        String input = "(and 7)";

        assertSExpressionsMatch(new LispNumber("7"), evaluateString(input));
    }

    @Test
    public void andWithSeveralValues() {
        String input = "(and t t nil t t)";

        assertNil(evaluateString(input));
    }

    @Test
    public void andWithSeveralNumbers() {
        String input = "(and 1 2 3)";

        assertSExpressionsMatch(new LispNumber("3"), evaluateString(input));
    }

    @Test(expected = UndefinedSymbolException.class)
    public void andShortCircuits() {
        String input = "(and nil (setq x 22))";

        assertNil(evaluateString(input));
        evaluateString("x");
    }

}