/** * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite * contributors * * This file is part of EvoSuite. * * EvoSuite is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3.0 of the License, or * (at your option) any later version. * * EvoSuite 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 * Lesser Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>. */ package org.evosuite.symbolic.solver; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.evosuite.symbolic.expr.Constraint; import org.evosuite.symbolic.expr.Variable; import org.evosuite.symbolic.expr.bv.IntegerVariable; import org.evosuite.symbolic.expr.fp.RealVariable; import org.evosuite.symbolic.expr.str.StringVariable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Interface for SMT solvers * * @author Gordon Fraser */ public abstract class Solver { private final boolean addMissingVariables; protected boolean addMissingVariables() { return addMissingVariables; } public Solver() { addMissingVariables = false; } public Solver(boolean addMissingVariables) { this.addMissingVariables = addMissingVariables; } static Logger logger = LoggerFactory.getLogger(Solver.class); /** * * @param constraints * a constraint system to be solved * * @return a non-null result that is SAT or UNSAT * @throws SolverTimeoutException * a timeout occurred while executing the solver * @throws IOException * an IOException occurred while executing the solver * @throws SolverParseException * the solver's result could not be parsed into a valid * SolverResult * @throws SolverEmptyQueryException * the solver * @throws SolverErrorException * the solver reported an error after its execution */ public abstract SolverResult solve(Collection<Constraint<?>> constraints) throws SolverTimeoutException, IOException, SolverParseException, SolverEmptyQueryException, SolverErrorException; /** * Returns a mapping from variables to their current concrete values. * * @param variables * @return a mapping from variables to their current concrete values. */ protected static Map<String, Object> getConcreteValues(Set<Variable<?>> variables) { Map<String, Object> concrete_values = new HashMap<String, Object>(); for (Variable<?> v : variables) { String var_name = v.getName(); Object concrete_value = v.getConcreteValue(); concrete_values.put(var_name, concrete_value); } return concrete_values; } /** * Creates a set with all the variables in the constraints. * * @param constraints * the constraint system * @return the set of variables in the constraint system */ protected static Set<Variable<?>> getVariables(Collection<Constraint<?>> constraints) { Set<Variable<?>> variables = new HashSet<Variable<?>>(); for (Constraint<?> c : constraints) { variables.addAll(c.getLeftOperand().getVariables()); variables.addAll(c.getRightOperand().getVariables()); } return variables; } /** * Restore all concrete values of the variables using the concrete_values * mapping. * * @param variables * @param concrete_values */ protected static void setConcreteValues(Set<Variable<?>> variables, Map<String, Object> concrete_values) { for (Variable<?> v : variables) { String var_name = v.getName(); if (!concrete_values.containsKey(var_name)) { continue; } Object concreteValue = concrete_values.get(var_name); if (v instanceof StringVariable) { StringVariable sv = (StringVariable) v; String concreteString = (String) concreteValue; sv.setConcreteValue(concreteString); } else if (v instanceof IntegerVariable) { IntegerVariable iv = (IntegerVariable) v; Long concreteInteger = (Long) concreteValue; iv.setConcreteValue(concreteInteger); } else if (v instanceof RealVariable) { RealVariable ir = (RealVariable) v; Double concreteReal = (Double) concreteValue; ir.setConcreteValue(concreteReal); } else { logger.warn("unknow variable type " + v.getClass().getName()); } } } private static final double DELTA = 1e-15; protected static boolean checkSAT(Collection<Constraint<?>> constraints, SolverResult satResult) { if (satResult == null) { throw new NullPointerException("satResult should be non-null"); } if (!satResult.isSAT()) { throw new IllegalArgumentException("satResult should be SAT"); } // back-up values Set<Variable<?>> variables = getVariables(constraints); Map<String, Object> initialValues = getConcreteValues(variables); // set new values Map<String, Object> newValues = satResult.getModel(); setConcreteValues(variables, newValues); // check SAT with new values double distance = DistanceEstimator.getDistance(constraints); // restore values setConcreteValues(variables, initialValues); if (distance <= DELTA) { return true; } else { return false; } } }