/*
 * Copyright (C) 2013 Matthew Dawson <matthew@mjdsystems.ca>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ca.mcmaster.cas.matlab2smt;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;

import java.util.Arrays;
import java.util.Collection;

import static org.junit.Assert.*;

/**
 * @author Matthew Dawson <matthew@mjdsystems.ca>
 */
@RunWith(Parameterized.class)
public class GenericGeneratorTest {
    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][]{
                {new SMTLIBGenerator(),
                        "(or (or (or (or (= (* x 5.0) (/ 1.0 (- 4.0))) (and (> x (+ 8.0 3.0)) (< 9.0 (- x 2.0)))) (>= x 12.0)) (not (<= 34.0 (- x)))) (> 5.0 4.0))",
                        null,
                        null},
                {new CVC3Generator(),
                        "((((((x * 5) = (1 / (- 4))) OR ((x > (8 + 3)) AND (9 < (x - 2)))) OR (x >= 12)) OR (NOT (34 <= (- x)))) OR (5 > 4))",
                        "(((((BVMULT(8,x,0bin00010100) = BVSDIV(0bin00000100,BVUMINUS(0bin00010000))) OR (BVSGT(x,BVPLUS(8,0bin00100000,0bin00001100)) AND BVSLT(0bin00100100,BVSUB(x,0bin00001000)))) OR BVSGE(x,0bin00110000)) OR (NOT BVSLE(0bin10001000,BVUMINUS(x)))) OR (5 > 4))",
                        "(((((BVMULT(8,x,0bin00010100) = BVUDIV(0bin00000100,BVUMINUS(0bin00010000))) OR (BVGT(x,BVPLUS(8,0bin00100000,0bin00001100)) AND BVLT(0bin00100100,BVSUB(x,0bin00001000)))) OR BVGE(x,0bin00110000)) OR (NOT BVLE(0bin10001000,BVUMINUS(x)))) OR (5 > 4))"
                }
        });
    }

    static private String query = "(x * 5) == (1 / -4) || ((x > (8 + 3)) && (9 < x - 2)) || x >= 12 || ~(34 <= -x) || (5 > 4)";
    static private VariableType outputType = new BooleanVariableType();

    @Parameter(value = 0)
    public CheckerGenerator generator;

    @Parameter(value = 1)
    public String RealExpectedOutput;

    @Parameter(value = 2)
    public String SignedFixedPointExpectedOutput;

    @Parameter(value = 3)
    public String UnsignedFixedPointExpectedOutput;

    @Test
    public void RealTest() {
        if (RealExpectedOutput != null) {
            VariableParser vars = new VariableParser("x");
            MatlabParser parser = new MatlabParser(vars, query);
            assertEquals(RealExpectedOutput, parser.getRootExpression().getCheckerOutput(generator, outputType));
        }
    }

    @Test
    public void SignedFixedPointTest() {
        if (SignedFixedPointExpectedOutput != null) {
            VariableParser vars = new VariableParser("x:fixedt(1, 8, 2)");
            MatlabParser parser = new MatlabParser(vars, query);
            assertEquals(SignedFixedPointExpectedOutput, parser.getRootExpression().getCheckerOutput(generator, outputType));
        }
    }

    @Test
    public void UnsignedFixedPointTest() {
        if (UnsignedFixedPointExpectedOutput != null) {
            VariableParser vars = new VariableParser("x:fixedt(0, 8, 2)");
            MatlabParser parser = new MatlabParser(vars, query);
            assertEquals(UnsignedFixedPointExpectedOutput, parser.getRootExpression().getCheckerOutput(generator, outputType));
        }
    }
}
