Skip to content

Commit 3be6621

Browse files
committed
v1.0.0 of dead code omission during PFP calculation
1 parent d16f0bc commit 3be6621

File tree

11 files changed

+285
-252
lines changed

11 files changed

+285
-252
lines changed

src/main/java/edu/uniandes/tsdl/mutapk/MutAPK.java

Lines changed: 175 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,15 @@
77
import java.io.FileWriter;
88
import java.io.FilenameFilter;
99
import java.io.IOException;
10-
import java.io.UnsupportedEncodingException;
1110
import java.nio.file.Paths;
1211
import java.util.HashMap;
13-
import java.util.Iterator;
1412
import java.util.List;
1513
import java.util.Map.Entry;
1614
import java.util.Set;
1715

1816
import javax.xml.parsers.ParserConfigurationException;
1917

2018
import org.antlr.runtime.RecognitionException;
21-
import org.antlr.runtime.tree.CommonTree;
2219
import org.json.simple.JSONObject;
2320
import org.json.simple.parser.JSONParser;
2421
import org.json.simple.parser.ParseException;
@@ -62,6 +59,7 @@ public class MutAPK {
6259
static String extraPath = "";
6360
static String operatorsDir = "";
6461
static boolean multithread = true;
62+
static boolean ignoreDeadCode = true;
6563
static String selectionStrategy = "";
6664

6765
// Optional arguments
@@ -75,6 +73,10 @@ public class MutAPK {
7573

7674
static HashMap<String, SmaliAST> smaliASTs = new HashMap<String, SmaliAST>();
7775

76+
static HashMap<String, HashMap<String, CallGraphNode>> callGraph = new HashMap<String, HashMap<String, CallGraphNode>>();
77+
78+
static HashMap<String, HashMap<String, CallGraphNode>> deadCode = new HashMap<String, HashMap<String, CallGraphNode>>();
79+
7880
public static void main(String[] args) {
7981
try {
8082
// long initialTime = System.currentTimeMillis();
@@ -122,102 +124,175 @@ public static void runMutAPK(String[] args) throws NumberFormatException, FileNo
122124
//--------------------------------------------
123125
// Run detection phase for AST-based detectors
124126
//--------------------------------------------
125-
126127
// Generate HashMap with all the ASTs
127128
SourceCodeProcessor scp = new SourceCodeProcessor();
128129
scp.generateASTsMap(extraPath, appName, smaliASTs);
130+
if(ignoreDeadCode) {
131+
132+
Long initTime = System.currentTimeMillis();
133+
134+
// Generate the Call Graph
135+
System.out.println("## Call Graph Results");
136+
System.out.println("");
137+
System.out.println("Method Type | Amount");
138+
System.out.println("----------------|---------");
139+
140+
callGraph = CallGraphHelper.getCallGraph(smaliASTs);
141+
int cNDC = 0;
142+
int cDC = 0;
143+
144+
for(Entry<String, HashMap<String, CallGraphNode>> entry : callGraph.entrySet()) {
145+
for(Entry<String, CallGraphNode> entryy : entry.getValue().entrySet()) {
146+
CallGraphNode cGN = entryy.getValue();
147+
boolean isDeadCode = methodIsDeadCode(cGN);
148+
if(!isDeadCode) {
149+
cNDC++;
150+
} else {
151+
if(deadCode.get(cGN.getUnitName())!=null) {
152+
deadCode.get(cGN.getUnitName()).put(cGN.getId(), cGN);
153+
} else {
154+
HashMap<String, CallGraphNode> temp = new HashMap<String, CallGraphNode>();
155+
temp.put(cGN.getId(), cGN);
156+
deadCode.put(cGN.getUnitName(), temp);
157+
}
158+
cDC++;
159+
}
160+
}
161+
}
162+
System.out.println("CalledAndDefined | "+cNDC);
163+
System.out.println("DeadCode | "+cDC);
164+
System.out.println("\n----------------------------------");
165+
166+
// Check Dead Code Methods
167+
168+
// for(Entry<String, HashMap<String, CallGraphNode>> entry : deadCode.entrySet()) {
169+
// System.out.println(entry.getKey());
170+
// for(Entry<String, CallGraphNode> entryy : entry.getValue().entrySet()) {
171+
// System.out.println(" "+entryy.getKey());
172+
// }
173+
// }
174+
175+
// Prune ASTs
176+
for(Entry<String, SmaliAST> entry: smaliASTs.entrySet()) {
177+
if(deadCode.get(entry.getKey())!=null) {
178+
smaliASTs.put(entry.getKey(), ASTHelper.pruneAST(entry.getValue(),deadCode.get(entry.getKey())));
179+
}
180+
}
181+
182+
Long duration = (System.currentTimeMillis()-initTime);
183+
System.out.println("");
184+
System.out.println("> It took "+duration+" miliseconds to remove dead code from APK analysis.");
185+
186+
187+
}
188+
// Generate PFP over pruned ASTs
189+
for(Entry<String, SmaliAST> entry : smaliASTs.entrySet()) {
190+
SmaliAST temp = entry.getValue();
191+
192+
HashMap<MutationType, List<MutationLocation>> fileLocations = ASTHelper.findLocations(temp, operatorBundle);
193+
appendLocations(fileLocations, locations);
194+
}
195+
196+
// Report the statistics of the found Potential Fault Locations
197+
Set<MutationType> keys = locations.keySet();
198+
List<MutationLocation> list = null;
199+
int totalMutants = 0;
200+
System.out.println("## Amount of Potential Fault Locations per Mutation Operator\n");
201+
System.out.println("Amount Mutants | Mutation Operator");
202+
System.out.println("----------------|---------------------");
203+
for (MutationType mutationType : keys) {
204+
list = locations.get(mutationType);
205+
totalMutants += list.size();
206+
System.out.println(list.size() + " | " + mutationType);
207+
}
208+
209+
// Check if the amount of PFLocations is lower than the requested by the user
210+
if(totalMutants < amountMutants) {
211+
throw new MutAPKException("The total of mutants need to be greater than the amount of mutants asked");
212+
}
213+
System.out.println("");
214+
215+
// Build MutationLocation List
216+
List<MutationLocation> mutationLocationList = MutationLocationListBuilder.buildList(locations);
217+
printLocationList(mutationLocationList, mutantsFolder, appName);
218+
System.out.println("\nTotal Locations: " + mutationLocationList.size());
219+
System.out.println();
220+
System.out.println("--------------------------------------");
221+
222+
// Select Selector
223+
switch (selectionStrategy) {
224+
case AMOUNT_MUTANTS_SS:
225+
SelectorAmountMutantsMethod selectorAmountMutantsMethod = new SelectorAmountMutantsMethod();
226+
SelectorAmountMutants selectorAmountMutants = new SelectorAmountMutants(false, false, totalMutants,
227+
amountMutants);
228+
mutationLocationList = selectorAmountMutantsMethod.mutantSelector(locations, selectorAmountMutants);
229+
break;
230+
case REPRESENTATIVE_SUBSET_SS:
231+
SelectorConfidenceInterval selectorConfidenceInterval = new SelectorConfidenceInterval(true, false,
232+
totalMutants, isRSPerOPerator, confidenceLevel, marginError);
233+
SelectorConfidenceIntervalMethod CIMS = new SelectorConfidenceIntervalMethod();
234+
mutationLocationList = CIMS.mutantSelector(locations, selectorConfidenceInterval);
235+
break;
236+
default:
237+
break;
238+
}
239+
System.out.println("");
240+
241+
System.out.println("## Mutation Process Log");
242+
System.out.println();
243+
System.out.println("```sh");
244+
245+
// Execute mutation phase
246+
MutationsProcessor mProcessor = new MutationsProcessor("temp", appName, mutantsFolder);
247+
248+
// Create de apkhash for the base folder
249+
File manifest = new File(apkAbsolutePath + File.separator + "AndroidManifest.xml");
250+
File smali = new File(apkAbsolutePath + File.separator + "smali");
251+
File resource = new File(apkAbsolutePath + File.separator + "res");
252+
129253

130-
// Generate the Call Graph
131-
132-
HashMap<String, HashMap<String, CallGraphNode>> callGraph = CallGraphHelper.getCallGraph(smaliASTs);
133-
134-
// for(Entry<String, HashMap<String, CallGraphNode>> entry : callGraph.entrySet()) {
135-
// System.out.println(entry.getKey());
136-
// for(Entry<String, CallGraphNode> entryy : entry.getValue().entrySet()) {
137-
// CallGraphNode temp = entryy.getValue();
138-
// System.out.println(" "+entryy.getKey()+" "+temp.getCallees().size()+" "+temp.getCallers().size());
139-
// }
140-
// }
141-
142-
// Prune ASTs
143-
144-
145-
// // Generate PFP over pruned ASTs
146-
// for(Entry<String, SmaliAST> entry : smaliASTs.entrySet()) {
147-
// SmaliAST temp = entry.getValue();
148-
//
149-
// HashMap<MutationType, List<MutationLocation>> fileLocations = ASTHelper.findLocations(temp, operatorBundle);
150-
// appendLocations(fileLocations, locations);
151-
// }
152-
//
153-
// // Report the statistics of the found Potential Fault Locations
154-
// Set<MutationType> keys = locations.keySet();
155-
// List<MutationLocation> list = null;
156-
// int totalMutants = 0;
157-
// System.out.println("## Amount of Potential Fault Locations per Mutation Operator\n");
158-
// System.out.println("Amount Mutants | Mutation Operator");
159-
// System.out.println("----------------|---------------------");
160-
// for (MutationType mutationType : keys) {
161-
// list = locations.get(mutationType);
162-
// totalMutants += list.size();
163-
// System.out.println(list.size() + " | " + mutationType);
164-
// }
165-
//
166-
// // Check if the amount of PFLocations is lower than the requested by the user
167-
// if(totalMutants < amountMutants) {
168-
// throw new MutAPKException("The total of mutants need to be greater than the amount of mutants asked");
169-
// }
170-
// System.out.println("");
171-
//
172-
// // Build MutationLocation List
173-
// List<MutationLocation> mutationLocationList = MutationLocationListBuilder.buildList(locations);
174-
// printLocationList(mutationLocationList, mutantsFolder, appName);
175-
// System.out.println("\nTotal Locations: " + mutationLocationList.size());
176-
// System.out.println();
177-
// System.out.println("--------------------------------------");
178-
//
179-
// // Select Selector
180-
// switch (selectionStrategy) {
181-
// case AMOUNT_MUTANTS_SS:
182-
// SelectorAmountMutantsMethod selectorAmountMutantsMethod = new SelectorAmountMutantsMethod();
183-
// SelectorAmountMutants selectorAmountMutants = new SelectorAmountMutants(false, false, totalMutants,
184-
// amountMutants);
185-
// mutationLocationList = selectorAmountMutantsMethod.mutantSelector(locations, selectorAmountMutants);
186-
// break;
187-
// case REPRESENTATIVE_SUBSET_SS:
188-
// SelectorConfidenceInterval selectorConfidenceInterval = new SelectorConfidenceInterval(true, false,
189-
// totalMutants, isRSPerOPerator, confidenceLevel, marginError);
190-
// SelectorConfidenceIntervalMethod CIMS = new SelectorConfidenceIntervalMethod();
191-
// mutationLocationList = CIMS.mutantSelector(locations, selectorConfidenceInterval);
192-
// break;
193-
// default:
194-
// break;
195-
// }
196-
// System.out.println("");
197-
//
198-
// System.out.println("## Mutation Process Log");
199-
// System.out.println();
200-
// System.out.println("```sh");
201-
//
202-
// // Execute mutation phase
203-
// MutationsProcessor mProcessor = new MutationsProcessor("temp", appName, mutantsFolder);
204-
//
205-
// // Create de apkhash for the base folder
206-
// File manifest = new File(apkAbsolutePath + File.separator + "AndroidManifest.xml");
207-
// File smali = new File(apkAbsolutePath + File.separator + "smali");
208-
// File resource = new File(apkAbsolutePath + File.separator + "res");
209-
//
210-
//
211-
// // Create ApkHashSeparator
212-
// ApkHashSeparator apkHashSeparator = mProcessor.generateApkHashSeparator(manifest, smali, resource, 0);
213-
// // Add the base apkHashSeparator
214-
// ApkHashOrder.getInstance().setApkHashSeparator(apkHashSeparator);
215-
//
216-
// if (multithread) {
217-
// mProcessor.processMultithreaded(mutationLocationList, extraPath, apkName);
218-
// } else {
219-
// mProcessor.process(mutationLocationList, extraPath, apkName);
220-
// }
254+
// Create ApkHashSeparator
255+
ApkHashSeparator apkHashSeparator = mProcessor.generateApkHashSeparator(manifest, smali, resource, 0);
256+
// Add the base apkHashSeparator
257+
ApkHashOrder.getInstance().setApkHashSeparator(apkHashSeparator);
258+
259+
if (multithread) {
260+
mProcessor.processMultithreaded(mutationLocationList, extraPath, apkName);
261+
} else {
262+
mProcessor.process(mutationLocationList, extraPath, apkName);
263+
}
264+
265+
}
266+
267+
private static boolean methodIsDeadCode(CallGraphNode cGN) {
268+
269+
String[] exceptions = new String[] {
270+
"<init>",
271+
"<clinit>",
272+
"init",
273+
"onClick",
274+
"onCreate",
275+
"onOptionsItemSelected",
276+
"onCreateOptionsMenu",
277+
"onResume",
278+
"update",
279+
"query",
280+
"getType",
281+
"insert",
282+
"doInBackground",
283+
"onPostExecute"
284+
};
285+
286+
if(cGN.getCallers().size()>0) {
287+
return false;
288+
}
289+
290+
for (int i = 0; i < exceptions.length; i++) {
291+
if(cGN.getId().startsWith(exceptions[i]+"(")) {
292+
return false;
293+
}
294+
}
295+
return true;
221296

222297
}
223298

@@ -248,9 +323,10 @@ private static void readConfig(String configFilePath) throws NumberFormatExcepti
248323
appName = getVariableValuesString(jsonObject, "appName");
249324
mutantsFolder = getVariableValuesString(jsonObject, "mutantsFolder");
250325
multithread = Boolean.valueOf(getVariableValuesString(jsonObject, "multithreadExec"));
326+
ignoreDeadCode = Boolean.valueOf(getOptionalVariableValuesString(jsonObject, "ignoreDeadCode"));
251327
selectionStrategy = getVariableValues(jsonObject, "selectionStrategy");
252-
operatorsDir = getOptionalVariableValuesString(jsonObject, "operatorsDir");
253-
extraPath = getOptionalVariableValuesString(jsonObject, "extraPath");
328+
operatorsDir = getVariableValuesString(jsonObject, "operatorsDir");
329+
extraPath = getVariableValuesString(jsonObject, "extraPath");
254330

255331
// Impreme valor por defecto
256332
System.out.println("");
@@ -264,6 +340,7 @@ private static void readConfig(String configFilePath) throws NumberFormatExcepti
264340
System.out.println("extraPath | " + extraPath);
265341
System.out.println("operatorsDir | " + operatorsDir);
266342
System.out.println("multithread | " + multithread);
343+
System.out.println("ignoreDeadCode | " + ignoreDeadCode);
267344
System.out.println("selectionStrategy | " + selectionStrategy);
268345

269346
JSONObject selectionParameters = (JSONObject) jsonObject.get("selectionParameters");
@@ -398,7 +475,7 @@ private static String getOptionalVariableValuesString(JSONObject jsonObject, Str
398475
if (temp != null) {
399476
return temp;
400477
} else {
401-
return "";
478+
return "true";
402479
}
403480
}
404481

0 commit comments

Comments
 (0)