package function.builtin.special;

import function.builtin.Eval.UndefinedSymbolException;
import org.junit.Test;
import sexpression.LispNumber;
import testutil.SymbolAndFunctionCleaner;

import static testutil.TestUtilities.assertSExpressionsMatch;
import static testutil.TestUtilities.evaluateString;
import static testutil.TypeAssertions.assertNil;
import static testutil.TypeAssertions.assertT;

public class ANDTest extends SymbolAndFunctionCleaner {

    @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");
    }
}