package fr.inria.diversify.issta2; import fr.inria.diversify.Profiling; import fr.inria.diversify.buildSystem.AbstractBuilder; import fr.inria.diversify.buildSystem.maven.MavenBuilder; import fr.inria.diversify.diversification.InputProgram; import fr.inria.diversify.logger.Comparator; import fr.inria.diversify.logger.Diff; import fr.inria.diversify.logger.transformationUsed.TransformationUsedReader; import fr.inria.diversify.transformation.SingleTransformation; import fr.inria.diversify.transformation.Transformation; import fr.inria.diversify.util.Log; import org.apache.commons.io.FileUtils; import spoon.reflect.cu.SourcePosition; import java.io.File; import java.io.IOException; import java.util.*; import java.util.stream.Collectors; /** * User: Simon * Date: 23/06/15 * Time: 14:29 */ public class SosieComparator { InputProgram inputProgram; AbstractBuilder originalBuilder; String tmpSosieDir; Set<Comparator> comparators; Map<Class, Diff> filter; Set<String> filterForTest; public SosieComparator(InputProgram inputProgram) { this.inputProgram = inputProgram; comparators = new HashSet<>(); filterForTest = new HashSet<>(); filter = new HashMap<>(); } public void init(String tmpDir) throws Exception { String dir = tmpDir + "_original"; copyDir(inputProgram.getProgramDir(), dir); instru(dir, null); originalBuilder = new MavenBuilder(dir); for(Comparator comparator : comparators) { comparator.init(inputProgram, originalBuilder); filter.put(comparator.getClass(), comparator.getEmptyDiff()); } tmpSosieDir = tmpDir + "_sosie"; } public Set<Diff> compare(SingleTransformation trans) throws Exception { try { Collection<String> testToRun = selectTest(trans.getPosition()); if(testToRun.isEmpty()) { return new HashSet<>(); } updateFilter(testToRun); copyDir(tmpSosieDir.substring(0, tmpSosieDir.length() - 6), tmpSosieDir); trans.applyWithParent(tmpSosieDir + "/" + inputProgram.getRelativeSourceCodeDir()); instru(tmpSosieDir, trans); AbstractBuilder sosieBuilder = new MavenBuilder(tmpSosieDir); return runAndCompare(sosieBuilder, trans, testToRun); } finally { trans.restore(tmpSosieDir); } } protected void updateFilter(Collection<String> testToRun) throws Exception { Set<String> tests = testToRun.stream() .filter(test -> !filterForTest.contains(test)) .collect(Collectors.toSet()); if(!tests.isEmpty()) { Log.debug("update filter for tests: {}", tests); run(originalBuilder, tests); File oldLog = new File(originalBuilder.getDirectory() + "/oldLog/"); File currentLog = new File(originalBuilder.getDirectory() + "/log/"); FileUtils.copyDirectory(currentLog, oldLog); run(originalBuilder, tests); for(Comparator comparator : comparators) { Diff diff = comparator.compare(null, originalBuilder.getDirectory() + "/oldLog/", originalBuilder.getDirectory() + "/log/"); filter.get(comparator.getClass()).merge(diff); } FileUtils.forceDelete(oldLog); } filterForTest.addAll(tests); } protected Collection<String> selectTest(SourcePosition position) { return comparators.stream() .flatMap(comparator -> comparator.selectTest(position).stream()) .collect(Collectors.toSet()); } protected Set<Diff> runAndCompare(AbstractBuilder sosieBuilder, SingleTransformation trans, Collection<String> testToRun) throws Exception { Set<Diff> diffs = new HashSet<>(); run(sosieBuilder, testToRun); run(originalBuilder, testToRun); for(Comparator comparator : comparators) { Diff diff = comparator.compare(trans, tmpSosieDir + "/log", originalBuilder.getDirectory() + "/log"); diff.filter(filter.get(comparator.getClass())); if(diff.size() != 0) { Log.info("{} diff", comparator.getClass().toString()); diffs.add(diff); } } TransformationUsedReader tu = new TransformationUsedReader(tmpSosieDir + "/log"); if (!tu.load().isEmpty()) { trans.setStatus(Transformation.EXE); } return diffs; } protected int run(AbstractBuilder builder, Collection<String> testToRun) throws InterruptedException, IOException { String goals = "test -Dmaven.compiler.useIncrementalCompilation=false -Dmaven.test.useIncrementalCompilation=false -Dtest=" + testToRun.stream() .collect(Collectors.joining(",")); File logDir = new File(builder.getDirectory() + "/log"); for(File file : logDir.listFiles()) { if(file.getName().startsWith("log")) { FileUtils.forceDelete(file); } } builder.runGoals(new String[]{goals}, true); return builder.getStatus(); } protected void copyDir(String src, String dest) throws IOException { File dir = new File(dest); if(dir.exists()) { FileUtils.forceDelete(dir); } dir.mkdirs(); FileUtils.copyDirectory(new File(src), dir); } protected void instru(String outputDirectory, SingleTransformation transformation) throws Exception { Properties properties = new Properties(); properties.put("profiling.main.transformationUsed", "true"); // properties.put("profiling.main.field", "true"); properties.put("profiling.main.branch", "true"); // properties.put("profiling.main.branch.addBodyBranch", "true"); // properties.put("profiling.main.catch", "true"); // properties.put("profiling.main.throw", "true"); properties.put("profiling.main.methodCall", "false"); properties.put("profiling.test.logTest", "true"); Profiling profiling = new Profiling(inputProgram, outputDirectory, "fr.inria.diversify.logger.logger", properties, transformation); profiling.apply(); } public void addComparator(Comparator comparator) { comparators.add(comparator); } }