/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ca.mcmaster.cas.matlab2smt.test;

import ca.mcmaster.cas.matlab2smt.BooleanVariableType;
import ca.mcmaster.cas.matlab2smt.CVC3Generator;
import ca.mcmaster.cas.matlab2smt.CheckerGenerator;
import ca.mcmaster.cas.matlab2smt.MatlabExpression;
import ca.mcmaster.cas.matlab2smt.MatlabLiteral;
import ca.mcmaster.cas.matlab2smt.MatlabParser;
import ca.mcmaster.cas.matlab2smt.RealVariableType;
import ca.mcmaster.cas.matlab2smt.SMTLIBGenerator;
import ca.mcmaster.cas.matlab2smt.Variable;
import ca.mcmaster.cas.matlab2smt.VariableParser;
import ca.mcmaster.cas.matlab2smt.VariableType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.junit.Assert.*;
import org.junit.Ignore;

/**
 *
 * @author matthew
 */
@RunWith(JUnit4.class)
public class MatlabParserTest {
    @Test
    public void testSimpleNumberParse() {
        MatlabParser parser = new MatlabParser(null, "5\n");
        MatlabExpression expr = parser.getRootExpression();
        VariableType variableType = new RealVariableType();
        
        assertSame(MatlabLiteral.class, expr.getClass());
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("5", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("5.0", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testSimpleRealVariableParse() {
        MatlabParser parser = new MatlabParser(new VariableParser("a"), "a\n");
        MatlabExpression expr = parser.getRootExpression();

        assertSame(Variable.class, expr.getClass());
        CheckerGenerator generator = new CVC3Generator();
        VariableType variableType = new RealVariableType();
        assertEquals("a", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("a", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testSimpleAdditionWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "4+5\n");
        MatlabExpression expr = parser.getRootExpression();

        CheckerGenerator generator = new CVC3Generator();
        VariableType variableType = new RealVariableType();
        assertEquals("(4 + 5)", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(+ 4.0 5.0)", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testSimpleMultiplicationWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "4*5\n");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new RealVariableType();
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("(4 * 5)", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(* 4.0 5.0)", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testSimpleNegationWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "~0\n");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new RealVariableType();
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("(NOT 0)", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(not 0.0)", expr.getCheckerOutput(generator, variableType));
    }

    @Test
    public void testDoubleAdditionWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "4+5+6\n");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new RealVariableType();
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("((4 + 5) + 6)", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(+ (+ 4.0 5.0) 6.0)", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testMultiplyThenAddWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "4*5+6\n");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new RealVariableType();
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("((4 * 5) + 6)", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(+ (* 4.0 5.0) 6.0)", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testAddThenMultiplyWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "4+5*6\n");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new RealVariableType();
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("(4 + (5 * 6))", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(+ 4.0 (* 5.0 6.0))", expr.getCheckerOutput(generator, variableType));
    }
    
    @Test
    public void testInsanseExpressionsWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "4*5+6*7\n");
        MatlabParser parser2 = new MatlabParser(null, "4+5+6*7*8\n");

        CheckerGenerator cvc3generator = new CVC3Generator();
        CheckerGenerator smtlibgenerator = new SMTLIBGenerator();

        VariableType variableType = new RealVariableType();
        assertEquals("((4 * 5) + (6 * 7))", parser.getRootExpression().getCheckerOutput(cvc3generator, variableType));
        assertEquals("(+ (* 4.0 5.0) (* 6.0 7.0))", parser.getRootExpression().getCheckerOutput(smtlibgenerator, variableType));

        assertEquals("((4 + 5) + ((6 * 7) * 8))", parser2.getRootExpression().getCheckerOutput(cvc3generator, variableType));
        assertEquals("(+ (+ 4.0 5.0) (* (* 6.0 7.0) 8.0))", parser2.getRootExpression().getCheckerOutput(smtlibgenerator, variableType));
    }
    
    @Test
    public void testSimpleConditionalsWithLiterals() {
        MatlabParser parser = new MatlabParser(null, "5 > 5\n");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new BooleanVariableType();
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("(5 > 5)", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(> 5.0 5.0)", expr.getCheckerOutput(generator, variableType));
    }

    @Test
    public void testInsanseExpressionsWithLiteralsAndVariables() {
        MatlabParser parser = new MatlabParser(new VariableParser("x,z,y"), "z == 1 && x == 0 && y == 2");
        MatlabExpression expr = parser.getRootExpression();

        VariableType variableType = new BooleanVariableType();
        assertEquals(variableType, expr.actualOutputTypeForRequestedOutput(variableType));
        CheckerGenerator generator = new CVC3Generator();
        assertEquals("(((z = 1) AND (x = 0)) AND (y = 2))", expr.getCheckerOutput(generator, variableType));
        generator = new SMTLIBGenerator();
        assertEquals("(and (and (= z 1.0) (= x 0.0)) (= y 2.0))", expr.getCheckerOutput(generator, variableType));
    }
}
