package kr.ac.snu.selab.soot; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import kr.ac.snu.selab.soot.analyzer.AbstractAnalyzer; import kr.ac.snu.selab.soot.core.AbstractProject; import kr.ac.snu.selab.soot.core.ProjectManager; import org.apache.log4j.Logger; import org.junit.Before; import org.junit.Test; import soot.Body; import soot.Hierarchy; import soot.Local; import soot.PackManager; import soot.RefType; import soot.Scene; import soot.SootClass; import soot.SootField; import soot.SootMethod; import soot.Transform; import soot.Unit; import soot.Value; import soot.ValueBox; import soot.jimple.internal.JAssignStmt; import soot.jimple.internal.JInvokeStmt; import soot.jimple.internal.JReturnStmt; import soot.jimple.internal.JReturnVoidStmt; import soot.jimple.toolkits.callgraph.CallGraph; public class SootAPITest { private static Logger logger = Logger.getLogger(SootAPITest.class); private static final String PROJECTS_NAME = "SparkTest"; private static final String PROJECTS_FILE_NAME = "projects.xml"; int targetClassCount = 0; @Before public void prepare() throws Throwable { targetClassCount = 0; ProjectManager projects = ProjectManager.getInstance(); FileInputStream fis = null; try { fis = new FileInputStream(findProjectsFile()); projects.loadProjects(fis); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { } } } AbstractProject project = projects.getProject(PROJECTS_NAME); assertNotNull("Cannot find project!!!", project); AbstractAnalyzer analyzer = new TestRunner(project); PackManager.v().getPack("jtp") .add(new Transform("jtp.Experiment", analyzer)); final String[] arguments = { "-cp", project.getClassPath(), "-f", "J", "-w", "-p", "cg.spark", "verbose:true,on-fly-cg:true", "-d", project.getJimpleDirectory(), "--process-dir", project.getSourceDirectory()}; soot.Main.main(arguments); } @Test public void classNumber() { //assertEquals(8, targetClassCount); } private class TestRunner extends AbstractAnalyzer { public TestRunner(AbstractProject project) { super(project); } @SuppressWarnings("unchecked") @Override protected void analyze(List<SootClass> classList, Hierarchy hierarchy) { CallGraph cg = Scene.v().getCallGraph(); assertNotNull("Target classes not found", classList); // assertEquals(7, classList.size()); targetClassCount = classList.size(); logger.debug("cg size: " + cg.size()); logger.debug("class number: " + classList.size()); for (SootClass aClass : classList) { logger.debug("###############################"); logger.debug("<Class> => " + aClass.toString()); logger.debug("###############################"); if (aClass.getName().equals("SubD")) { assertTrue(aClass.getFields().isEmpty()); for (SootField fieldOfSubD : aClass.getFields()) { logger.debug("inherited field test"); logger.debug("aField => " + fieldOfSubD.getSignature()); logger.debug("aField.getType() => " + fieldOfSubD.getType().toString()); } } for (SootField aField : aClass.getFields()) { if (aField.getName().equals("list")) { SootClass fieldClass = ((RefType)aField.getType()).getSootClass(); RefType listType = RefType.v("java.util.List"); SootClass listTypeClass = listType.getSootClass(); assertEquals(fieldClass, listTypeClass); } if (aField.getName().equals("tList")) { SootClass fieldClass = ((RefType)aField.getType()).getSootClass(); RefType listType = RefType.v("java.util.List"); SootClass listTypeClass = listType.getSootClass(); assertEquals(fieldClass, listTypeClass); } } for (SootMethod aMethod : aClass.getMethods()) { logger.debug("<Method> => " + aMethod.getSignature()); logger.debug("SootMethod.getName() => " + aMethod.getName()); logger.debug("**************************"); if (aMethod.hasActiveBody()) { Body body = aMethod.getActiveBody(); Iterator<Local> localIter = body.getLocals().iterator(); logger.debug("----Locals----"); while (localIter.hasNext()) { logger.debug("local: " + localIter.next().toString()); } logger.debug("----Params----"); int numOfParam = aMethod.getParameterCount(); for (int i = 0; i < numOfParam; i++) { logger.debug(body.getParameterLocal(i).toString()); } logger.debug("----Units----"); List<Unit> units = new ArrayList<Unit>(); units.addAll(body.getUnits()); for (Unit aUnit : units) { if (aUnit instanceof JReturnStmt) { logger.debug("<JReturnStmt>"); logger.debug(aUnit); logger.debug("Value JReturnStmt.getOp() => " + ((JReturnStmt)aUnit).getOp()); } if (aUnit instanceof JReturnVoidStmt) { logger.debug("<JReturnVoidStmt>"); logger.debug(aUnit); } if (aUnit instanceof JInvokeStmt) { logger.debug("<JInvokeStmt>"); logger.debug(aUnit); JInvokeStmt stmt = (JInvokeStmt)aUnit; if (stmt.containsInvokeExpr()) { logger.debug("InvokeExpr JInvokeStmt.getInvokeExpr() =>" + stmt.getInvokeExpr()); logger.debug("InvokeExpr JInvokeStmt.getInvokeExpr().getClass().toString()=>" + stmt.getInvokeExpr().getClass().toString()); logger.debug("ValueBox JInvokeStmt.getInvokeExprBox() => " + stmt.getInvokeExprBox()); logger.debug("Type InvokeExpr.getType() => " + stmt.getInvokeExpr().getType()); logger.debug("SootMethod InvokeExpr.getMethod() => " + stmt.getInvokeExpr().getMethod()); logger.debug("SootMethodRef InvokeExpr.getMethodRef() => " + stmt.getInvokeExpr().getMethodRef()); logger.debug("List<ValueBox> InvokeExpr.getUseBoxes() =>"); List<ValueBox> useBoxes = stmt.getInvokeExpr().getUseBoxes(); for (ValueBox box : useBoxes) { logger.debug(box.getValue().toString()); } List<Local> args = new ArrayList<Local>(); args = stmt.getInvokeExpr().getArgs(); logger.debug("List InvokeExpr.getArgs() => "); for (Local arg : args) { logger.debug(arg.toString()); } } } if (aUnit instanceof JAssignStmt) { logger.debug("<JAssignStmt>"); logger.debug(aUnit); JAssignStmt stmt = (JAssignStmt)aUnit; if (stmt.containsFieldRef()) { logger.debug("JAssignStmt.getFieldRef() => " + stmt.getFieldRef().toString()); logger.debug("JAssignStmt.getFieldRefBox() => " + stmt.getFieldRefBox().toString()); logger.debug("JAssignStmt.getFieldRef().getField() => " + stmt.getFieldRef().getField().toString()); } logger.debug("JAssingStmt.getRightOp() => " + stmt.getRightOp().toString()); logger.debug("JAssignStmt.getRightOp().getType() => " + stmt.getRightOp().getType().toString()); logger.debug("JAssingStmt.getRightOp().getClass() => " + stmt.getRightOp().getClass().toString()); if (stmt.containsInvokeExpr()) { logger.debug("JAssingStmt.getInvokeExpr().getClass().toString() => " + stmt.getInvokeExpr().getClass().toString()); } logger.debug("--------RightOp--------"); List<ValueBox> valueboxes = stmt.getRightOp().getUseBoxes(); List<Value> values = new ArrayList<Value>(); for (ValueBox valuebox : valueboxes) { logger.debug("valuebox => " + valuebox); logger.debug("valuebox.getClass() => " + valuebox.getClass()); values.add(valuebox.getValue()); } for (Value value : values) { logger.debug("value => " + value); logger.debug("value.getClass() => " + value.getClass()); } if (stmt.containsInvokeExpr()) { logger.debug("List<ValueBox> InvokeExpr.getUseBoxes() =>"); List<ValueBox> useBoxes = stmt.getInvokeExpr().getUseBoxes(); for (ValueBox box : useBoxes) { logger.debug(box.getValue().toString()); } } } } } logger.debug("**************************"); } } } } private static File findProjectsFile() { URL url = ClassLoader.getSystemResource(PROJECTS_FILE_NAME); if (url == null) { return null; } File file = new File(url.getFile()); if (file == null || !file.exists() || !file.isFile()) { return null; } return file; } }