package fr.inria.diversify;
import fr.inria.diversify.buildSystem.maven.MavenBuilder;
import fr.inria.diversify.buildSystem.maven.MavenDependencyResolver;
import fr.inria.diversify.diversification.InputConfiguration;
import fr.inria.diversify.diversification.InputProgram;
import fr.inria.diversify.factories.SpoonMetaFactory;
import fr.inria.diversify.persistence.json.input.JsonSosiesInput;
import fr.inria.diversify.persistence.json.output.JsonSosiesOutput;
import fr.inria.diversify.transformation.Transformation;
import fr.inria.diversify.util.Log;
import org.codehaus.plexus.util.FileUtils;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collection;
import static fr.inria.diversify.transformation.Transformation.EXCEPTION;
import static fr.inria.diversify.transformation.Transformation.SOSIE;
/**
* Takes a series of corrected transformations and check if they are still sosies
*/
public class CorrectedTransformationsToSosie {
//private static final String CONF_PATH = "C:\\MarcelStuff\\data\\DIVERSE\\input_configurations\\CheckSosies-CommonColl.properties";
//Readed transformations
private ArrayList<Transformation> transformations;
//Confirmed soses
private ArrayList<Transformation> sosies;
public static void main(String[] args) throws Exception {
new CorrectedTransformationsToSosie().start(args[0]);
}
private void start(String confPath) throws Exception {
Log.INFO();
InputConfiguration inputConfiguration = new InputConfiguration(confPath);
verifyTransformations(inputConfiguration);
}
/**
* Verify that transformations are indeed sosies
*
* @param inputConfiguration
*/
private void verifyTransformations(InputConfiguration inputConfiguration) throws Exception {
Log.info("Creating tmp dir");
initPath(inputConfiguration);
Log.info("Creating tmp dir completed");
//Path for resulting files of sosies and non-sosies
String transfPath = inputConfiguration.getResultPath() + "/coll-minus_sosies.json";
String sosiePath = inputConfiguration.getResultPath() + System.currentTimeMillis() + ".sosies.json" ;
sosies = new ArrayList<>();
//Load transformations and previously created sosies (if any)
Log.info("Loading transformations");
if ( new File(transfPath).exists() )
transformations = loadWithSosiesInput(inputConfiguration, transfPath);
else
transformations = loadWithSosiesInput(inputConfiguration,
inputConfiguration.getPreviousTransformationPath());
Log.info("Loading transformations completed");
Log.info("Transformation size: " + transformations.size());
while (transformations.size() > 0) {
Transformation t = transformations.get(transformations.size() - 1);
int status;
try {
Log.info("Applying transformation");
status = applyTransformation(inputConfiguration, t);
Log.info("Transformation applied successfully. Build status: " + status);
} catch (Exception e) {
status = EXCEPTION;
}
if (status == EXCEPTION) {
Log.info("Exception!!");
//Try to recover by reseting the whole thing
initPath(inputConfiguration);
if (new File(transfPath).exists())
transformations = loadWithSosiesInput(inputConfiguration, transfPath);
Log.info("Recovering from exception successful");
}
transformations.remove(transformations.size() - 1);
//Save the transformations
JsonSosiesOutput transfOut = new JsonSosiesOutput(
transformations, transfPath, inputConfiguration.getProjectPath() + "\\pom.xml",
InputConfiguration.LATEST_GENERATOR_VERSION);
transfOut.write();
if (status == SOSIE) {
sosies.add(t);
//Save the sosies
JsonSosiesOutput sosieOut = new JsonSosiesOutput(transformations, sosiePath,
inputConfiguration.getProjectPath() + "\\pom.xml", InputConfiguration.LATEST_GENERATOR_VERSION);
sosieOut.write();
}
Log.info("Sosies so far: " + sosies.size());
Log.info("Transformation remaining: " + transformations.size());
}
}
private void initPath(InputConfiguration inputConfiguration) throws IOException {
//Copy project to tmp folder
File prj = new File(inputConfiguration.getProjectPath());
File tmp = new File(inputConfiguration.getTempDir());
FileUtils.copyDirectoryStructure(prj, tmp);
}
/**
* Applies the transformation:
* 1. Creates a new factory
* 2.
*
* @param inputConfiguration
* @param t
*/
private int applyTransformation(InputConfiguration inputConfiguration, Transformation t) throws Exception {
String s = inputConfiguration.getTempDir() + "/src/main/java";
int status = Transformation.NOT_TESTED;
try {
t.apply(s);
status = runTests(inputConfiguration);
t.restore(s);
} catch (Exception e) {
return EXCEPTION;
}
return status;//AbstractTransformation.NOT_TESTED;
}
private int runTests(InputConfiguration inputConfiguration) throws InterruptedException, IOException {
MavenBuilder rb = new MavenBuilder(inputConfiguration.getTempDir());
rb.setTimeOut(0);
rb.runGoals(new String[]{"clean", "test"}, true);
return rb.getStatus();
}
/**
* Loads the sosies with the JsonSosiesInput
*
* @param inputConfiguration Input configuration to load
* @return The collection of transformations loaded
* @throws Exception
*/
private ArrayList<Transformation> loadWithSosiesInput(
InputConfiguration inputConfiguration, String transfPath) throws Exception {
MavenDependencyResolver dr = new MavenDependencyResolver();
dr.DependencyResolver(inputConfiguration.getProjectPath() + "\\pom.xml");
InputProgram p = new InputProgram();
p.configure(inputConfiguration);
long t = System.currentTimeMillis();
p.setFactory(new SpoonMetaFactory().buildNewFactory(inputConfiguration.getRelativeSourceCodeDir(), 7));
Log.info("Build: " + Math.abs(System.currentTimeMillis() - t));
t = System.currentTimeMillis();
p.processCodeFragments();
Log.info("Process code fragment Time: " + Math.abs(System.currentTimeMillis() - t));
t = System.currentTimeMillis();
JsonSosiesInput input = new JsonSosiesInput(transfPath, p);
Collection<Transformation> r = input.read();
Log.info("Read Time: " + Math.abs(System.currentTimeMillis() - t));
return new ArrayList<>(r);
}
protected static void suicide() {
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
Log.debug("suicide");
Log.debug("PID :" + pid);
Runtime r = Runtime.getRuntime();
try {
r.exec("kill " + pid);
} catch (Exception e) {
Log.error("suicide ", e);
}
}
}