org.evosuite.symbolic.solver.z3str2.Z3Str2Solver Maven / Gradle / Ivy
The newest version!
/**
* Copyright (C) 2010-2018 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 .
*/
package org.evosuite.symbolic.solver.z3str2;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.io.FileUtils;
import org.evosuite.Properties;
import org.evosuite.symbolic.expr.Constraint;
import org.evosuite.symbolic.expr.Variable;
import org.evosuite.symbolic.solver.SmtExprBuilder;
import org.evosuite.symbolic.solver.SolverEmptyQueryException;
import org.evosuite.symbolic.solver.SolverErrorException;
import org.evosuite.symbolic.solver.SolverParseException;
import org.evosuite.symbolic.solver.SolverResult;
import org.evosuite.symbolic.solver.SolverTimeoutException;
import org.evosuite.symbolic.solver.SubProcessSolver;
import org.evosuite.symbolic.solver.smt.SmtAssertion;
import org.evosuite.symbolic.solver.smt.SmtCheckSatQuery;
import org.evosuite.symbolic.solver.smt.SmtConstantDeclaration;
import org.evosuite.symbolic.solver.smt.SmtExpr;
import org.evosuite.symbolic.solver.smt.SmtFunctionDefinition;
import org.evosuite.symbolic.solver.smt.SmtIntVariable;
import org.evosuite.symbolic.solver.smt.SmtOperation;
import org.evosuite.symbolic.solver.smt.SmtOperation.Operator;
import org.evosuite.symbolic.solver.smt.SmtOperatorCollector;
import org.evosuite.symbolic.solver.smt.SmtRealVariable;
import org.evosuite.symbolic.solver.smt.SmtStringVariable;
import org.evosuite.symbolic.solver.smt.SmtVariable;
import org.evosuite.symbolic.solver.smt.SmtVariableCollector;
import org.evosuite.symbolic.solver.z3.Z3Solver;
import org.evosuite.testcase.execution.EvosuiteError;
import org.evosuite.utils.FileIOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Z3Str2Solver extends SubProcessSolver {
private static final String EVOSUITE_Z3_STR_FILENAME = "evosuite.z3";
static Logger logger = LoggerFactory.getLogger(Z3Solver.class);
private static int dirCounter = 0;
public Z3Str2Solver() {
super();
}
public Z3Str2Solver(boolean addMissingVariables) {
super(addMissingVariables);
}
private static File createNewTmpDir() {
File dir = null;
String dirName = FileUtils.getTempDirectoryPath() + File.separator + "EvoSuiteZ3Str_" + (dirCounter++) + "_"
+ System.currentTimeMillis();
// first create a tmp folder
dir = new File(dirName);
if (!dir.mkdirs()) {
logger.error("Cannot create tmp dir: " + dirName);
return null;
}
if (!dir.exists()) {
logger.error(
"Weird behavior: we created folder, but Java cannot determine if it exists? Folder: " + dirName);
return null;
}
return dir;
}
private static SmtCheckSatQuery buildSmtQuerty(Collection> constraints) {
ConstraintToZ3Str2Visitor v = new ConstraintToZ3Str2Visitor();
List assertions = new LinkedList();
SmtVariableCollector varCollector = new SmtVariableCollector();
SmtOperatorCollector opCollector = new SmtOperatorCollector();
for (Constraint> c : constraints) {
SmtExpr smtExpr = c.accept(v, null);
if (smtExpr != null) {
SmtAssertion newAssertion = new SmtAssertion(smtExpr);
assertions.add(newAssertion);
smtExpr.accept(varCollector, null);
smtExpr.accept(opCollector, null);
}
}
Set smtVariables = varCollector.getSmtVariables();
Set smtOperators = opCollector.getOperators();
boolean addCharToIntFunction;
if (smtOperators.contains(SmtOperation.Operator.CHAR_TO_INT)) {
addCharToIntFunction = true;
} else {
addCharToIntFunction = false;
}
Set smtVariablesToDeclare = new HashSet(smtVariables);
if (addCharToIntFunction) {
Set charVariables = buildCharVariables();
smtVariablesToDeclare.addAll(charVariables);
}
List constantDeclarations = new LinkedList();
for (SmtVariable v1 : smtVariablesToDeclare) {
String varName = v1.getName();
if (v1 instanceof SmtIntVariable) {
SmtConstantDeclaration constantDecl = SmtExprBuilder.mkIntConstantDeclaration(varName);
constantDeclarations.add(constantDecl);
} else if (v1 instanceof SmtRealVariable) {
SmtConstantDeclaration constantDecl = SmtExprBuilder.mkRealConstantDeclaration(varName);
constantDeclarations.add(constantDecl);
} else if (v1 instanceof SmtStringVariable) {
SmtConstantDeclaration constantDecl = SmtExprBuilder.mkStringConstantDeclaration(varName);
constantDeclarations.add(constantDecl);
} else {
throw new RuntimeException("Unknown variable type " + v1.getClass().getCanonicalName());
}
}
List functionDefinitions = new LinkedList();
if (addCharToIntFunction) {
String charToInt = buildCharToIntFunction();
SmtFunctionDefinition newFunctionDef = new SmtFunctionDefinition(charToInt);
functionDefinitions.add(newFunctionDef);
}
SmtCheckSatQuery smtCheckSatQuery = new SmtCheckSatQuery(constantDeclarations, functionDefinitions, assertions);
return smtCheckSatQuery;
}
@Override
public SolverResult solve(Collection> constraints) throws SolverTimeoutException, IOException,
SolverParseException, SolverEmptyQueryException, SolverErrorException {
SmtCheckSatQuery smtCheckSatQuery = buildSmtQuerty(constraints);
if (smtCheckSatQuery.getConstantDeclarations().isEmpty()) {
logger.debug("Z3-str2 input has no variables");
throw new SolverEmptyQueryException("Z3-str2 input has no variables");
}
if (smtCheckSatQuery.getAssertions().isEmpty()) {
Map emptySolution = new HashMap();
SolverResult emptySAT = SolverResult.newSAT(emptySolution);
return emptySAT;
}
Z3Str2QueryPrinter printer = new Z3Str2QueryPrinter();
String smtQueryStr = printer.print(smtCheckSatQuery);
logger.debug("Z3-str2 input:");
logger.debug(smtQueryStr);
int timeout = (int) Properties.DSE_CONSTRAINT_SOLVER_TIMEOUT_MILLIS;
File tempDir = createNewTmpDir();
String z3TempFileName = tempDir.getAbsolutePath() + File.separatorChar + EVOSUITE_Z3_STR_FILENAME;
if (Properties.Z3_STR2_PATH == null) {
String errMsg = "Property Z3_STR_PATH should be setted in order to use the Z3StrSolver!";
logger.error(errMsg);
throw new IllegalStateException(errMsg);
}
try {
FileIOUtils.writeFile(smtQueryStr, z3TempFileName);
String z3Cmd = Properties.Z3_STR2_PATH + " -f " + z3TempFileName;
ByteArrayOutputStream stdout = new ByteArrayOutputStream();
launchNewProcess(z3Cmd, smtQueryStr, timeout, stdout);
String z3str2ResultStr = stdout.toString("UTF-8");
Z3Str2ResultParser parser = new Z3Str2ResultParser();
Set> variables = getVariables(constraints);
Map initialValues = getConcreteValues(variables);
SolverResult solverResult;
if (addMissingVariables()) {
solverResult = parser.parse(z3str2ResultStr, initialValues);
} else {
solverResult = parser.parse(z3str2ResultStr);
}
if (solverResult.isSAT()) {
// check if solution is correct, otherwise return UNSAT
boolean check = checkSAT(constraints, solverResult);
if (!check) {
logger.debug("Z3-str2 solution does not solve the constraint system!");
SolverResult unsatResult = SolverResult.newUNSAT();
return unsatResult;
}
}
return solverResult;
} catch (UnsupportedEncodingException e) {
throw new EvosuiteError("UTF-8 should not cause this exception!");
} finally {
File tempFile = new File(z3TempFileName);
if (tempFile.exists()) {
tempFile.delete();
}
}
}
private final static int ASCII_TABLE_LENGTH = 90;
private static Set buildCharVariables() {
Set charVariables = new HashSet();
for (int i = 0; i < ASCII_TABLE_LENGTH; i++) {
char c = (char) i;
String str = String.valueOf(c);
String encodedStr = ExprToZ3Str2Visitor.encodeString(str);
SmtStringVariable v = new SmtStringVariable(encodedStr);
charVariables.add(v);
}
return charVariables;
}
private static String buildCharToIntFunction() {
StringBuffer buff = new StringBuffer();
buff.append(SmtOperation.Operator.CHAR_TO_INT + "((x!1 String)) Int");
buff.append("\n");
for (int i = 0; i < ASCII_TABLE_LENGTH; i++) {
char c = (char) i;
String str = String.valueOf(c);
String encodedStr = ExprToZ3Str2Visitor.encodeString(str);
if (i < ASCII_TABLE_LENGTH - 1) {
String iteStr = String.format("(ite (= x!1 %s) %s", encodedStr, i);
buff.append(iteStr);
buff.append("\n");
} else {
buff.append(i);
}
}
for (int i = 0; i < ASCII_TABLE_LENGTH - 1; i++) {
buff.append(")");
}
buff.append("\n");
return buff.toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy