package fr.inria.diversify.logger.branch; import fr.inria.diversify.buildSystem.AbstractBuilder; import fr.inria.diversify.diversification.InputProgram; import fr.inria.diversify.logger.Comparator; import fr.inria.diversify.logger.Diff; import fr.inria.diversify.processor.main.BranchPositionProcessor; import fr.inria.diversify.transformation.SingleTransformation; import fr.inria.diversify.util.Log; import fr.inria.diversify.util.LoggerUtils; import org.apache.commons.io.FileUtils; import spoon.reflect.cu.SourcePosition; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * User: Simon * Date: 23/06/15 * Time: 14:40 */ public class BranchComparator implements Comparator { Map<String, Set<String>> testsByBranch; Map<String, SourcePosition> branchPosition; @Override public void init(InputProgram originalInputProgram, AbstractBuilder originalBuilder) throws Exception { Log.debug("init BranchComparator"); initTestByBranch(originalBuilder); intBranch(originalInputProgram); } @Override public Diff compare(SingleTransformation transformation, String originalLogDir, String sosieLogDir) throws Exception { List<TestCoverage> sosieCoverage = loadTestCoverage(sosieLogDir); List<TestCoverage> originalCoverage = loadTestCoverage(originalLogDir); boolean filterTransformationPosition = filterTransformationPosition(transformation, originalCoverage, sosieCoverage); BranchDiff diff = new BranchDiff(); for(TestCoverage originalTestCoverage : originalCoverage) { TestCoverage sosieTestCoverage = sosieCoverage.stream() .filter(tc -> tc.getTestName().equals(originalTestCoverage.getTestName())) .findFirst() .get(); if(!originalTestCoverage.containsAllBranch(sosieTestCoverage)) { Set<String> originalBranches = originalTestCoverage.getCoveredBranch(); Set<String> sosieBranches = sosieTestCoverage.getCoveredBranch(); Set<String> d1 = originalBranches.stream() .filter(branch -> !sosieBranches.contains(branch)) .filter(branch -> !filterTransformationPosition || !(branch.contains(transformation.classLocationName()) && branch.contains(transformation.methodLocationName()))) .collect(Collectors.toSet()); Set<String> d2 = sosieBranches.stream() .filter(branch -> !originalBranches.contains(branch)) .filter(branch -> !filterTransformationPosition || !(branch.contains(transformation.classLocationName()) && branch.contains(transformation.methodLocationName()))) .collect(Collectors.toSet()); d1.addAll(d2); if(!d1.isEmpty()) { diff.addBranchDiff(originalTestCoverage.getTestName(), d1); } } } return diff; } protected boolean filterTransformationPosition(SingleTransformation transformation, List<TestCoverage> originalCoverage, List<TestCoverage> sosieCoverage) { if(transformation == null) { return false; } String className = transformation.classLocationName(); String methodName = transformation.methodLocationName(); Set<String> originalBranches = allBranchesOf(originalCoverage, className, methodName); Set<String> sosieBranches = allBranchesOf(sosieCoverage, className, methodName); return !originalBranches.equals(sosieBranches); } protected Set<String> allBranchesOf(List<TestCoverage> testCoverages, String className, String methodName) { return testCoverages.stream() .flatMap(coverage -> coverage.getCoverage().getMethodCoverages().stream()) .filter(methodCoverage -> methodCoverage.getMethodName().contains("_" + methodName) && methodCoverage.getMethodName().contains(className+ "_")) .flatMap(methodCoverage -> methodCoverage.getAllBranch().stream()) .collect(Collectors.toSet()); } protected void initTestByBranch(AbstractBuilder originalBuilder) throws InterruptedException, IOException { testsByBranch = new HashMap<>(); writePropertiesFile(originalBuilder.getDirectory() + "/log"); originalBuilder.runGoals(new String[]{"clean", "test"}, false); deletePropertiesFile(originalBuilder.getDirectory() + "/log"); List<TestCoverage> testCoverage = loadTestCoverage(originalBuilder.getDirectory() + "/log"); for(TestCoverage tc : testCoverage) { for(MethodCoverage mth : tc.getCoverage().getMethodCoverages()) { for(Branch branch : mth.getCoveredBranchs()) { String key = mth.getMethodId() + "." + branch.getId(); if (!testsByBranch.containsKey(key)) { testsByBranch.put(key, new HashSet<>()); } String testName = tc.getTestName(); int ind = testName.lastIndexOf("."); testName = new StringBuilder(testName).replace(ind, ind + 1, "#").toString(); // testName = testName.substring(0, ind); testsByBranch.get(key).add(testName); } } } } protected void writePropertiesFile(String fileName) throws IOException { FileWriter writer = new FileWriter(fileName + "/options"); writer.write("fullPath=false\n"); writer.write("writeVar=false\n"); writer.write("logMethodCall=false\n"); writer.close(); } protected void deletePropertiesFile(String fileName) throws IOException { File file = new File(fileName + "/options"); FileUtils.forceDelete(file); } protected void intBranch(InputProgram originalInputProgram) { BranchPositionProcessor processor = new BranchPositionProcessor(originalInputProgram); LoggerUtils.applyProcessor(originalInputProgram.getFactory(), processor); branchPosition = processor.getBranchPosition(); } protected List<TestCoverage> loadTestCoverage(String logDir) throws IOException { CoverageReader reader = new CoverageReader(logDir); List<TestCoverage> result = reader.loadTest(); return result; } protected boolean branchContainsIn(SingleTransformation trans, Set<String> branches) { return branches.stream() .filter(branch -> !(branch.contains(trans.classLocationName()) && branch.contains(trans.methodLocationName()))) .count() == 0; } public Collection<String> selectTest(SourcePosition sourcePosition) { return branchPosition.keySet().stream() .filter(branch -> include(branchPosition.get(branch),sourcePosition)) .filter(branch -> testsByBranch.containsKey(branch)) .flatMap(branch -> testsByBranch.get(branch).stream()) .collect(Collectors.toSet()); } @Override public Diff getEmptyDiff() { return new BranchDiff(); } //true if oThis include in oOther protected boolean include(SourcePosition oThis, SourcePosition oOther) { return oThis.getCompilationUnit().getMainType().getQualifiedName().equals(oOther.getCompilationUnit().getMainType().getQualifiedName()) && oThis.getLine() <= oOther.getLine() && oThis.getEndLine() >= oOther.getEndLine(); } // public String branchFor(CtElement element) { // String info = ""; // int branchId = 0; // for(Object object : Query.getElements(element, new TypeFilter(CtIf.class))) { // info += ";t" + branchId; // info += ";e" + branchId; // branchId++; // } // // for(Object object : Query.getElements(element, new TypeFilter(CtCase.class))) { // info += ";s" + branchId; // branchId++; // } // // for(Object object : Query.getElements(element, new TypeFilter(CtLoop.class))) { // // info += ";l" + branchId; // branchId++; // } // for(Object object : Query.getElements(element, new TypeFilter(CtCatch.class))) { // info += ";c" + branchId; // branchId++; // } // // return info; // } }