package edu.ncsu.muclipse.exec;
import mujava.ClassMutantsGenerator;
import mujava.MutationSystem;
import mujava.OpenJavaException;
import mujava.TestExecuter;
import mujava.TraditionalMutantsGenerator;
import mujava.test.TestResult;
import mujava.util.Debug;
import mujava.cmd.MutantsGenerator;
import java.io.*;
import java.util.Formatter;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.logging.StreamHandler;
import org.eclipse.osgi.framework.internal.protocol.StreamHandlerFactory;
/**
* A Java Program which creates mutants with a given set of
* parameters. Called by MuClipse with a given runtime config.
* @author Ben Smith
*/
public class CreateMutants {
/**
* Determines how much console output there is.
*/
public static final boolean debug = true;
/**
* The ClassLevel Operators
*/
public static String[] cm_operators = { "IHI","IHD","IOD","IOP","IOR","ISI","ISD","IPC", // 8��
"PNC","PMD","PPD","PCI","PCC","PCD","PRV", // 7��
"OMR","OMD","OAN", // 3��
"JTI","JTD","JSI","JSD","JID","JDC", // 6��
"EOA","EOC","EAM","EMM" }; // 4�� - �� 28��
/**
* The Traditional Operators
*/
public static String[] tm_operators = { "AORB","AORS","AOIU","AOIS","AODU","AODS",
"ROR","COR","COD","COI","SOR","LOR","LOI","LOD","ASRS"};
/**
* The method which actually performs the mutation on
* the java classes.
* <p />
* Takes the following parameters in a String array:<br />
* 0: Full name of the project<br />
* 1: Location of the source<br />
* 2: Corresonding binaries<br />
* 3: Desired output folder<br />
* 4: Location of the test source<br />
* 5: List of traditional operators to run<br />
* 6: List of classlevel operators to run<br />
* 7: List of files to be mutated<br />
* @param args The parameters for this run. See above.
*/
public static void main(String[] args)
{
String syshome = args[0];
syshome = syshome.substring(0, syshome.length() - 1);
String source = "/" + args[1];
String classes = "/" + args[2];
String result = "/" + args[3];
// String tests = "/" + args[4];
String tradList = args[5];
String classList = args[6];
String theClassFile = args[7];
boolean[] traditional = new boolean[tradList.length()];
traditional = BitStringToBools(tradList);
boolean[] classlevel = new boolean[classList.length()];
classlevel = BitStringToBools(classList);
if (debug)
{
System.out.println("MuClipse v1.3 -- Rev 2");
System.out.println("MuClipse is generating mutants...");
System.out.println("For project located in:\n" + syshome);
System.out.println("Source located in: " + source);
System.out.println("Classes located in: " + classes);
System.out.println("Results located in: " + result);
System.out.println("Using these method-level mutants: ");
for (int i=0;i<tm_operators.length; i++)
{
if (traditional[i])
System.out.print(tm_operators[i] + ",");
}
System.out.println("\nAnd Using these class-level mutants: ");
for (int i=0;i<cm_operators.length; i++)
{
if (classlevel[i])
System.out.print(cm_operators[i] + ",");
}
}
String[] tradops = BitStringToArray(
args[5], tm_operators);
String[] classops = BitStringToArray(
args[6], cm_operators);
Debug.setDebugLevel(3);
try
{
MutationSystem.setJMutationStructure(syshome, source, classes, result);
validateOrCreate(MutationSystem.MUTANT_HOME);
MutationSystem.recordInheritanceRelation();
String file_name = theClassFile;
try{
System.out.println("Mutating class: " + file_name);
// [1] Examine if the target class is interface or abstract class
// In that case, we can't apply mutation testing.
// Generate class name from file_name
String temp = file_name.substring(0,file_name.length()-".java".length());
String class_name="";
for(int j=0;j<temp.length();j++){
if( (temp.charAt(j)=='\\') || (temp.charAt(j)=='/') ){
class_name = class_name + ".";
}else{
class_name = class_name + temp.charAt(j);
}
}
System.out.println();
File f = new File(MutationSystem.MUTANT_HOME + "/" + class_name + "/testresults.mjv");
System.out.println("Deleting: " + MutationSystem.MUTANT_HOME + "/" + class_name + "/testresults.mjv");
while (f.delete());
Class c = Class.forName(class_name);
int class_type = MutationSystem.getClassType(class_name);
if(class_type==MutationSystem.NORMAL){
}else if(class_type==MutationSystem.MAIN){
System.out.println(" -- " + file_name+ " class contains 'static void main()' method.");
System.out.println(" Pleas note that mutants are not generated for the 'static void main()' method");
}else{
switch(class_type){
case MutationSystem.INTERFACE :
System.out.println(" -- Can't apply because " + file_name+ " is 'interface' ");
break;
case MutationSystem.ABSTRACT :
System.out.println(" -- Can't apply because " + file_name+ " is 'abstract' class ");
break;
case MutationSystem.APPLET :
System.out.println(" -- Can't apply because " + file_name+ " is 'applet' class ");
break;
case MutationSystem.GUI :
System.out.println(" -- Can't apply because " + file_name+ " is 'GUI' class ");
break;
}
deleteDirectory();
return;
}
// [2] Apply mutation testing
setMutationSystemPathFor(file_name);
//File[] original_files = new File[1];
//original_files[0] = new File(MutationSystem.SRC_PATH,file_name);
File original_file = new File(MutationSystem.SRC_PATH,file_name);
/*AllMutantsGenerator genEngine;
genEngine = new AllMutantsGenerator(original_file,class_ops,traditional_ops);
genEngine.makeMutants();
genEngine.compileMutants();*/
ClassMutantsGenerator cmGenEngine;
cmGenEngine = new ClassMutantsGenerator(original_file,classops);
cmGenEngine.makeMutants();
cmGenEngine.compileMutants();
TraditionalMutantsGenerator tmGenEngine;
tmGenEngine = new TraditionalMutantsGenerator(original_file,tradops);
tmGenEngine.makeMutants();
tmGenEngine.compileMutants();
}catch(OpenJavaException oje){
System.out.println("[OJException] " + file_name + " " + oje.toString());
//System.out.println("Can't generate mutants for " +file_name + " because OpenJava " + oje.getMessage());
deleteDirectory();
}catch(Exception exp){
System.out.println("[Exception] " + file_name + " " + exp.toString());
exp.printStackTrace();
//System.out.println("Can't generate mutants for " +file_name + " due to exception" + exp.getClass().getName());
//exp.printStackTrace();
deleteDirectory();
}catch(Error er){
System.out.println("[Error] " + file_name + " " + er.toString());
//System.out.println("Can't generate mutants for " +file_name + " due to error" + er.getClass().getName());
deleteDirectory();
}
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("---------------------------");
System.out.println("Mutants have been created!");
}
/**
* Converts a String of '1's and '0's to corresponding
* boolean values.
* @param bits The String passed in
* @return A String array of corresponding booleans.
*/
public static boolean[] BitStringToBools(String bits)
{
boolean[] toRet = new boolean[bits.length()];
for (int i=0;i<bits.length();i++)
{
toRet[i] = (bits.charAt(i) == '1');
}
return toRet;
}
/**
* Converts a String of '1's and '0's to a list of mutation
* operators from the given String array of operators.<p />
*
* So if bitString = "101" and ops={"AOIS","AORB","COI"}
* then {"AOIS", "COI"} will be returned.
* @param bitString The passed in String
* @param ops The list of mutation operators to choose from
* @return A String array of which mutation operators to use
*/
public static String[] BitStringToArray(String bitString, String[] ops)
{
boolean[] thebools = BitStringToBools(bitString);
int cnt = 0;
for (int i=0;i<thebools.length;i++)
{
if (thebools[i])
cnt++;
}
String[] toRet = new String[cnt];
int j = 0;
for (int i=0;i<thebools.length;i++)
{
if (thebools[i])
{
toRet[j] = ops[i];
j++;
}
}
return toRet;
}
static void deleteDirectory(){
File originalDir = new File(MutationSystem.MUTANT_HOME+"/"+MutationSystem.DIR_NAME
+ "/" + MutationSystem.ORIGINAL_DIR_NAME);
while(originalDir.delete()){
}
File cmDir = new File(MutationSystem.MUTANT_HOME+"/"+MutationSystem.DIR_NAME
+ "/" + MutationSystem.CM_DIR_NAME);
while(cmDir.delete()){}
File tmDir = new File(MutationSystem.MUTANT_HOME+"/"+MutationSystem.DIR_NAME
+ "/" + MutationSystem.TM_DIR_NAME);
while(tmDir.delete()){}
File myHomeDir = new File(MutationSystem.MUTANT_HOME+"/"+MutationSystem.DIR_NAME);
while(myHomeDir.delete()){}
}
private static void validateOrCreate(String mutantDir)
{
System.out.println("Verifying the existence of: " + mutantDir);
File mutants = new File(mutantDir);
if (mutants.isDirectory())
{
System.out.println("The directory exists!");
return;
}
else
{
System.out.println("The directory was created: " + mutants.mkdir());
}
}
private static void setMutationSystemPathFor(String file_name){
try{
String temp;
temp = file_name.substring(0,file_name.length()-".java".length());
temp = temp.replace('/','.');
temp = temp.replace('\\','.');
int separator_index = temp.lastIndexOf(".");
if(separator_index>=0){
MutationSystem.CLASS_NAME=temp.substring(separator_index+1,temp.length());
}else{
MutationSystem.CLASS_NAME = temp;
}
String mutant_dir_path = MutationSystem.MUTANT_HOME+"/"+temp;
File mutant_path = new File(mutant_dir_path);
mutant_path.mkdir();
String class_mutant_dir_path = mutant_dir_path + "/" + MutationSystem.CM_DIR_NAME;
File class_mutant_path = new File(class_mutant_dir_path);
class_mutant_path.mkdir();
String traditional_mutant_dir_path = mutant_dir_path + "/" + MutationSystem.TM_DIR_NAME;
File traditional_mutant_path = new File(traditional_mutant_dir_path);
traditional_mutant_path.mkdir();
String original_dir_path = mutant_dir_path + "/" + MutationSystem.ORIGINAL_DIR_NAME;
File original_path = new File(original_dir_path);
original_path.mkdir();
MutationSystem.CLASS_MUTANT_PATH = class_mutant_dir_path;
MutationSystem.TRADITIONAL_MUTANT_PATH = traditional_mutant_dir_path;
MutationSystem.ORIGINAL_PATH = original_dir_path;
MutationSystem.DIR_NAME = temp;
}catch(Exception e){
System.err.println(e);
}
}
}