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 ORTester {

    private ExecutionContext executionContext;

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

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

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

    @Test
    public void orByItself() {
        String input = "(or)";

        assertNil(evaluateString(input));
    }

    @Test
    public void orWithNil() {
        String input = "(or nil)";

        assertNil(evaluateString(input));
    }

    @Test
    public void orWithT() {
        String input = "(or t)";

        assertT(evaluateString(input));
    }

    @Test
    public void orWithNumber() {
        String input = "(or 7)";

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

    @Test
    public void orWithSeveralValues() {
        String input = "(or nil nil nil t nil)";

        assertT(evaluateString(input));
    }

    @Test
    public void orWithSeveralNumbers() {
        String input = "(or 1 2 3)";

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

    @Test(expected = UndefinedSymbolException.class)
    public void orShortCircuits() {
        String input = "(or t (setf x 22))";

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

}
