/**
* Copyright (C) 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mujava.cli;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* <p>
* Description: The Class doRandomGivenMutationOperator.
* Overview: This class is used to calculate mutation scores
* based on randomly generated adequate test set of given mutation operators.
* Experiment use only.
* </p>
*
* @author Lin Deng
* @version 1.0 $Date: 06/10/2014 $
*/
public class doRandomGivenMutationOperator {
/**
* The main method.
*
* @param args
* the arguments
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public static void main(String[] args) throws IOException {
// need result file name
// String[] argv = { "/Users/dmark/COVDLsExpCopy/Triangle/result_list_2014_7_22_11_13_35.csv", "twoPred", "CDL", "10",
// "/Users/dmark/COVDLsExpCopy/Triangle/" };
String path = args[0];
String target = args[2];
int numOfRandom = Integer.valueOf(args[3]);
if (numOfRandom < 1) {
System.out.println("need more random times");
return;
}
String resultPath = args[4];
ArrayList<String> targets = new ArrayList<>();
// used for getting results
// if no target is selected, randomly take one test
// targets.add("SDL");
// targets.add("ODL");
// targets.add("VDL");
// targets.add("CDL");
// targets.add("SDL");targets.add("ODL");
// targets.add("SDL");targets.add("VDL");
// targets.add("SDL");targets.add("CDL");
// targets.add("VDL");targets.add("CDL");
// targets.add("SDL");targets.add("VDL");targets.add("CDL");
// read in file into data structure
HashMap<String, ArrayList<String>> result = readResultsFromFile(path);
// get all tests names
ArrayList<String> testNames = result.get("Mutant");
// need a filtered map based on target
HashMap<String, ArrayList<String>> filtered_data = getFilteredDataBasedOnTargets(result, targets);
// get the adequate test set
// CopyOnWriteArrayList<ArrayList<String>> adequateTestSet = getAdequateTestSets4(filtered_data, testNames);
// randomly get N adequate test set
ArrayList<ArrayList<String>> randomedTestSet = new ArrayList<>();
for(int i = 0; i < numOfRandom; i++)
{
randomedTestSet.add(getAdequateTestSets4(filtered_data, testNames));
}
// calculate each one with mutation score
ArrayList<Pair> mutationScores = getMutationScores(randomedTestSet, path);
double totalMS = 0.0;
for (Pair ms : mutationScores)
{
System.out.println(ms.testSet + ": " + ms.mutationScore);
totalMS=totalMS+ms.mutationScore;
}
double avgMS = totalMS / mutationScores.size();
System.out.println("avg: " + avgMS);
// write files
writeResultToFiles(mutationScores, resultPath, targets);
}
/**
* Write result to files.
*
* @param mutationScores the mutation scores
* @param resultPath the result path
* @param targets the targets
* @throws UnsupportedEncodingException the unsupported encoding exception
* @throws IOException Signals that an I/O exception has occurred.
*/
private static void writeResultToFiles(ArrayList<Pair> mutationScores, String resultPath, ArrayList<String> targets)
throws UnsupportedEncodingException, IOException {
resultPath=resultPath+"ResultOfRandomAdequateTests_"+targets+".txt";
// set the output file
File file = new File(resultPath);
FileOutputStream fout = new FileOutputStream(file);
StringBuffer fileContent = new StringBuffer();
double totalMS = 0.0;
for (Pair pair : mutationScores) {
totalMS = totalMS + pair.mutationScore;
fileContent.append(pair.testSet + ": " + pair.mutationScore);
fileContent.append("\r\n");
}
double avgMS = totalMS / mutationScores.size();
fileContent.append("Avg: " + avgMS);
fout.write(fileContent.toString().getBytes("utf-8"));
fout.close();
}
/**
* Gets the filtered data based on targets.
*
* @param result
* the result
* @param targets
* the targets
* @return the filtered data based on targets
*/
private static HashMap<String, ArrayList<String>> getFilteredDataBasedOnTargets(
HashMap<String, ArrayList<String>> result, ArrayList<String> targets) {
HashMap<String, ArrayList<String>> filtered_data = new HashMap<String, ArrayList<String>>();
for (String target : targets) {
for (Object key : result.keySet()) {
if (key.toString().contains(target))
filtered_data.put(key.toString(), result.get(key));
}
}
return filtered_data;
}
/**
* Read results from file. Note: This result include the fist title line.
* e.g. {VDL_3=[, 1, 1, 1, 2], Mutant=[test4, test1, test2, test3, Total,
* Equiv?], VDL_4=[1, 1, 1, , 3, y], VDL_5=[1, , 1, , 2]}
*
* @param path
* the path
* @return the hash map
* @throws IOException
* Signals that an I/O exception has occurred.
*/
private static HashMap<String, ArrayList<String>> readResultsFromFile(String path) throws IOException {
// read the file
File f = new File(path);
if (!f.exists()) {
System.out.println("Can't find file at: " + path);
return null;
}
// read in file into data structure
HashMap<String, ArrayList<String>> result = new HashMap<>();
String s = null;
StringBuffer sb = new StringBuffer();
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
while ((s = br.readLine()) != null) {
// split line
List<String> tests = Arrays.asList(s.split(",\\s*"));
// System.out.println(tests.get(1));
ArrayList<String> list = new ArrayList<>();
for (int i = 1; i < tests.size(); i++) {
list.add(tests.get(i));
}
result.put(tests.get(0), list);
}
return result;
}
/**
* Gets the mutation scores.
*
* @param randomedTestSet the randomed test set
* @param path the path
* @return the mutation scores
* @throws IOException Signals that an I/O exception has occurred.
*/
private static ArrayList<Pair> getMutationScores(ArrayList<ArrayList<String>> randomedTestSet, String path)
throws IOException {
// read in file into data structure, this result includes title line
HashMap<String, ArrayList<String>> result = readResultsFromFile(path);
// get all tests names
ArrayList<String> testNames = result.get("Mutant");
// build result with names, i.e. VDL_3=[test1, test2, test3],
// VDL_4=[test4, test1, test2], VDL_5=[test4, test2]
HashMap<String, ArrayList<String>> resultWithTestNames = getResultsWithNames(result);
// calculate
// get total number
int totalNumOfMutants = resultWithTestNames.size();
// get equiv number
int numOfEq = 0;
for (Object key : result.keySet()) {
if (result.get(key).contains("y") || result.get(key).contains("Y")) // has
// an
// equiv
{
numOfEq++;
}
}
ArrayList<Pair> mutationScores = new ArrayList<>();
// get killed number
// for each test test set, calculate how many killed mutants
for (ArrayList<String> tests : randomedTestSet) {
int numOfKilledMutants = 0;
for (Object key : resultWithTestNames.keySet()) // for each mutant
{
for (String test : tests) // for each test in current test set
{
if (resultWithTestNames.get(key).contains(test)) // current
// test
// kills
// current
// mutant
{
numOfKilledMutants++;
break; // directly go to the next mutant
}
}
}
// save mutation score
double ms = (double)numOfKilledMutants / (double)(totalNumOfMutants - numOfEq);
mutationScores.add(new Pair(tests, ms));
}
return mutationScores;
}
/**
* Gets the results with names.
*
* @param result the result
* @return the results with names
*/
private static HashMap<String, ArrayList<String>> getResultsWithNames(HashMap<String, ArrayList<String>> result) {
// get all tests names
ArrayList<String> testNames = result.get("Mutant");
// build result with names
HashMap<String, ArrayList<String>> resultWithTestNames = new HashMap<>();
HashMap<String, Integer> resultStat = new HashMap<>();
for (Object key : result.keySet()) {
ArrayList<String> temp = result.get(key);
ArrayList<String> testStrings = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
if (temp.get(i).equals("1") && !testNames.get(i).equals("Total")) // current test kills the current
// mutant
{
testStrings.add(testNames.get(i));
if (resultStat.containsKey(testNames.get(i)))
resultStat.put(testNames.get(i), resultStat.get(testNames.get(i)) + 1);
else {
resultStat.put(testNames.get(i), 1);
}
}
}
if (!key.toString().equals("Mutant"))
resultWithTestNames.put(key.toString(), testStrings);
}
return resultWithTestNames;
}
/**
* Gets the adequate test sets.
*
* @param filtered_data the filtered_data
* @param testNamesCopy the test names copy
* @return the adequate test sets4
*/
public static ArrayList<String> getAdequateTestSets4 (HashMap<String, ArrayList<String>> filtered_data,
ArrayList<String> testNamesCopy) {
CopyOnWriteArrayList<ArrayList<String>> testSets = new CopyOnWriteArrayList<ArrayList<String>>();
CopyOnWriteArrayList<String> mutantStrings = new CopyOnWriteArrayList<>();
HashMap<String, ArrayList<String>> resultWithTestNames = new HashMap<>();
HashMap<String, Integer> resultStat = new HashMap<>();
ArrayList<String> testNames = new ArrayList<>(testNamesCopy);
// get all mutants name in filtered data
for (Object key : filtered_data.keySet()) {
mutantStrings.add(key.toString());
ArrayList<String> temp = filtered_data.get(key);
ArrayList<String> testStrings = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
if (temp.get(i).equals("1") && !testNames.get(i).equals("Total")) // current test kills the current
// mutant
{
testStrings.add(testNames.get(i));
if (resultStat.containsKey(testNames.get(i)))
resultStat.put(testNames.get(i), resultStat.get(testNames.get(i)) + 1);
else {
resultStat.put(testNames.get(i), 1);
}
}
}
resultWithTestNames.put(key.toString(), testStrings);
}
// check if there is an equivalent
int numOfEq = 0;
int numOfTotalMutants = filtered_data.size();
ArrayList<String> nonEquivNonKilled = new ArrayList<>();
// remove those weren't be killed
for (Object key : filtered_data.keySet()) {
if (filtered_data.get(key).contains("y") ||
filtered_data.get(key).contains("Y") ||
filtered_data.get(key).contains("n") ||
filtered_data.get(key).contains("N")||
filtered_data.get(key).contains("?")
)
{
mutantStrings.remove(key.toString());
}
}
testNames.remove("Total");
testNames.remove("Equiv?");
ArrayList<String> result = new ArrayList<>();
int[] mutants = new int[mutantStrings.size()];
// for each mutant, randomly find a test that kills it
for(int i =0; i<mutantStrings.size();i++)
{
if(mutants[i]==1)
continue;
// get all tests that kill it
ArrayList<String> testsKillCurrentMutant = resultWithTestNames.get(mutantStrings.get(i));
// randomly choose one
SecureRandom random = new SecureRandom();
String randomTest = testsKillCurrentMutant.get(random.nextInt(testsKillCurrentMutant.size()));
result.add(randomTest);
// remove this mutant by marking the array to 1
mutants[i] = 1;
// remove other mutants that killed by the same test
for (int j =0; j<mutantStrings.size();j++)
{
if(mutants[j]==1)
continue;
if(resultWithTestNames.get(mutantStrings.get(j)).contains(randomTest))
// the test selected killed this m
{
mutants[j] = 1;
}
}
}
// System.out.println(result);
return result;
}
}