diff --git a/src/main/java/br/unb/cic/analysis/Main.java b/src/main/java/br/unb/cic/analysis/Main.java index f19ee792..a6aa40d2 100644 --- a/src/main/java/br/unb/cic/analysis/Main.java +++ b/src/main/java/br/unb/cic/analysis/Main.java @@ -28,24 +28,23 @@ public class Main { + private static CommandLine cmd; private Options options; private AbstractMergeConflictDefinition definition; private Set targetClasses; private List conflicts = new ArrayList<>(); private ReachDefinitionAnalysis analysis; - - public static void main(String args[]) { Main m = new Main(); try { m.createOptions(); CommandLineParser parser = new DefaultParser(); - CommandLine cmd = parser.parse(m.options, args); - - String mode = "dataflow"; - + cmd = parser.parse(m.options, args); + + String mode = "dataflow"; + if (cmd.hasOption("mode")) { mode = cmd.getOptionValue("mode"); } @@ -58,16 +57,14 @@ public static void main(String args[]) { m.loadDefinition(cmd.getOptionValue("csv")); } m.runAnalysis(mode, m.parseClassPath(cmd.getOptionValue("cp"))); - + m.exportResults(); - - } - catch(ParseException e) { + + } catch (ParseException e) { System.out.println("Error: " + e.getMessage()); HelpFormatter formatter = new HelpFormatter(); - formatter.printHelp( "java Main", m.options ); - } - catch(Exception e) { + formatter.printHelp("java Main", m.options); + } catch (Exception e) { e.printStackTrace(); } } @@ -75,9 +72,9 @@ public static void main(String args[]) { private String parseClassPath(String cp) { File f = new File(cp); String res = cp; - if(f.exists() && f.isDirectory()) { - for(File file : f.listFiles()) { - if(file.getName().endsWith(".jar")) { + if (f.exists() && f.isDirectory()) { + for (File file : f.listFiles()) { + if (file.getName().endsWith(".jar")) { res += ":"; res += file.getAbsolutePath(); } @@ -87,31 +84,30 @@ private String parseClassPath(String cp) { } private void exportResults() throws Exception { - System.out.println(" Analysis results"); + System.out.println(" Analysis results"); System.out.println("----------------------------"); - - if(conflicts.size() == 0) { - System.out.println(" No conflicts detected"); - System.out.println("----------------------------"); - return; + + if (conflicts.size() == 0) { + System.out.println(" No conflicts detected"); + System.out.println("----------------------------"); + return; } - + System.out.println(" Number of conflicts: " + conflicts.size()); - final String out = "out.txt"; + final String out = "out.txt"; final FileWriter fw = new FileWriter(out); conflicts.forEach(c -> { - try { + try { fw.write(c + "\n\n"); + } catch (Exception e) { + System.out.println("error exporting the results " + e.getMessage()); } - catch(Exception e) { - System.out.println("error exporting the results " + e.getMessage()); - } - }); + }); fw.close(); System.out.println(" Results exported to " + out); System.out.println("----------------------------"); } - + private void createOptions() { options = new Options(); Option classPathOption = Option.builder("cp").argName("class-path") @@ -136,23 +132,29 @@ private void createOptions() { .hasArg().desc("the commit merge to analysis") .build(); - Option verbose = Option.builder("verbose").argName("verbose").desc("run in the verbose mode").build(); - Option recursive = Option.builder("recursive").argName("recursive") + Option verboseOption = Option.builder("verbose").argName("verbose").hasArg().desc("run in the verbose mode").build(); + + Option recursiveOption = Option.builder("recursive").argName("recursive").hasArg() .desc("run using the recursive strategy for mapping sources and sinks") .build(); + Option oaDepthLimitOption = Option.builder("oaDepthLimit").argName("oaDepthLimit").hasArg() + .desc("sets the depth limit on accessing methods when performing Overriding Assignment " + + "Interprocedural analysis") + .build(); + options.addOption(classPathOption); options.addOption(inputFileOption); options.addOption(analysisOption); options.addOption(repoOption); options.addOption(commitOption); - options.addOption(verbose); - options.addOption(recursive); + options.addOption(verboseOption); + options.addOption(recursiveOption); + options.addOption(oaDepthLimitOption); } - private void runAnalysis(String mode, String classpath) { - switch(mode) { + switch (mode) { case "svfa-interprocedural": runSparseValueFlowAnalysis(classpath, true); break; @@ -178,7 +180,7 @@ private void runAnalysis(String mode, String classpath) { runDataFlowAnalysis(classpath, mode); } } - + private void runPessimisticDataFlowAnalysis(String classpath) { PackManager.v().getPack("jtp").add( new Transform("jtp.analysis", new BodyTransformer() { @@ -202,17 +204,21 @@ protected void internalTransform(Body body, String s, Map map) { .execute(); } - private void runDataFlowAnalysis(String classpath, String mode) { PackManager.v().getPack("jtp").add( new Transform("jtp.analysis", new BodyTransformer() { @Override protected void internalTransform(Body body, String phaseName, Map options) { - switch(mode) { - case "dataflow" : analysis = new ReachDefinitionAnalysis(body, definition); break; - case "tainted" : analysis = new TaintedAnalysis(body, definition); - case "confluence" : analysis = new ConfluentAnalysis(body, definition); break; + switch (mode) { + case "dataflow": + analysis = new ReachDefinitionAnalysis(body, definition); + break; + case "tainted": + analysis = new TaintedAnalysis(body, definition); + case "confluence": + analysis = new ConfluentAnalysis(body, definition); + break; case "confluence-tainted": analysis = new ConfluentTaintedAnalysis(body, definition); break; @@ -237,8 +243,10 @@ protected void internalTransform(Body body, String phaseName, Map classes = Collections.singletonList(classpath); SootWrapper.configureSootOptionsToRunInterproceduralOverrideAssignmentAnalysis(classes); @@ -246,7 +254,7 @@ private void runInterproceduralOverrideAssignmentAnalysis(String classpath) { interproceduralOverrideAssignment.configureEntryPoints(); PackManager.v().getPack("wjtp").add(new Transform("wjtp.analysis", interproceduralOverrideAssignment)); - SootWrapper.configurePackagesWithCallGraph().forEach(p -> PackManager.v().getPack(p).apply()); + SootWrapper.applyPackages(); conflicts.addAll(interproceduralOverrideAssignment.getConflicts().stream().map(c -> c.toString()).collect(Collectors.toList())); } @@ -289,8 +297,8 @@ private void runSparseValueFlowAnalysis(String classpath, boolean interprocedura private void runSparseValueFlowConfluenceAnalysis(String classpath, boolean interprocedural) { definition.setRecursiveMode(options.hasOption("recursive")); - SVFAConfluenceAnalysis analysis = new SVFAConfluenceAnalysis(classpath, this.definition, interprocedural); - + SVFAConfluenceAnalysis analysis = new SVFAConfluenceAnalysis(classpath, this.definition, interprocedural); + analysis.execute(); conflicts.addAll(analysis.getConfluentConflicts() .stream() @@ -304,11 +312,10 @@ private void loadDefinition(String filePath) throws Exception { Map> sourceDefs = new HashMap<>(); Map> sinkDefs = new HashMap<>(); targetClasses = new HashSet<>(); - for(ClassChangeDefinition change : changes) { - if(change.getType().equals(Statement.Type.SOURCE)) { + for (ClassChangeDefinition change : changes) { + if (change.getType().equals(Statement.Type.SOURCE)) { addChange(sourceDefs, change); - } - else { + } else { addChange(sinkDefs, change); } targetClasses.add(change.getClassName()); @@ -327,10 +334,9 @@ protected Map> sinkDefinitions() { } private void addChange(Map> map, ClassChangeDefinition change) { - if(map.containsKey(change.getClassName())) { + if (map.containsKey(change.getClassName())) { map.get(change.getClassName()).add(change.getLineNumber()); - } - else { + } else { List lines = new ArrayList<>(); lines.add(change.getLineNumber()); map.put(change.getClassName(), lines); @@ -366,17 +372,13 @@ protected Map> sinkDefinitions() { } private void addChangeFromDiffAnalysis(Map> map, Entry change) { - if(map.containsKey(change.getKey())) { + if (map.containsKey(change.getKey())) { map.get(change.getKey()).add(change.getValue()); - } - else { + } else { List lines = new ArrayList<>(); lines.add(change.getValue()); map.put(change.getKey(), lines); } } - - - } diff --git a/src/main/java/br/unb/cic/analysis/SootWrapper.java b/src/main/java/br/unb/cic/analysis/SootWrapper.java index ae646ea3..b08b1821 100644 --- a/src/main/java/br/unb/cic/analysis/SootWrapper.java +++ b/src/main/java/br/unb/cic/analysis/SootWrapper.java @@ -1,5 +1,6 @@ package br.unb.cic.analysis; +import soot.PackManager; import soot.Scene; import soot.jimple.spark.SparkTransformer; import soot.jimple.toolkits.callgraph.CHATransformer; @@ -40,7 +41,7 @@ public void execute() { } private static List getIncludeList() { - //"java.lang.*" + //"java.lang.*, java.util.*" List stringList = new ArrayList(Arrays.asList("java.util.*")); //java.util.HashMap return stringList; } @@ -63,16 +64,10 @@ public static void configureSootOptionsToRunInterproceduralOverrideAssignmentAna Scene.v().loadNecessaryClasses(); enableSparkCallGraph(); + //enableCHACallGraph(); } - public static List configurePackagesWithCallGraph() { - List packages = new ArrayList(); - packages.add("cg"); - packages.add("wjtp"); - return packages; - } - - public static void enableSparkCallGraph() { + private static void enableSparkCallGraph() { //Enable Spark HashMap opt = new HashMap(); //opt.put("propagator","worklist"); @@ -86,10 +81,23 @@ public static void enableSparkCallGraph() { soot.options.Options.v().setPhaseOption("cg.spark", "enable:true"); } - public static void enableCHACallGraph() { + private static void enableCHACallGraph() { CHATransformer.v().transform(); } + private static List configurePackagesWithCallGraph() { + List packages = new ArrayList(); + packages.add("cg"); + packages.add("wjtp"); + return packages; + } + + public static void applyPackages() { + configurePackagesWithCallGraph().forEach(p -> { + PackManager.v().getPack(p).apply(); + }); + } + public static class Builder { private String classPath; private String classes; diff --git a/src/main/java/br/unb/cic/analysis/df/DataFlowAbstraction.java b/src/main/java/br/unb/cic/analysis/df/DataFlowAbstraction.java index c50c1cf3..f1003325 100644 --- a/src/main/java/br/unb/cic/analysis/df/DataFlowAbstraction.java +++ b/src/main/java/br/unb/cic/analysis/df/DataFlowAbstraction.java @@ -7,7 +7,7 @@ import soot.jimple.InvokeStmt; import soot.jimple.StaticFieldRef; -import java.util.*; +import java.util.Objects; /** * Information wee keep while traversing @@ -99,4 +99,9 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(local, stmt); } + + @Override + public String toString() { + return "DataFlowAbstraction{ " + stmt + "}"; + } } diff --git a/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java b/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java index 324909e4..1dae3471 100644 --- a/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java +++ b/src/main/java/br/unb/cic/analysis/ioa/InterproceduralOverrideAssignment.java @@ -9,10 +9,13 @@ import br.unb.cic.exceptions.ValueNotHandledException; import soot.*; import soot.jimple.*; +import soot.jimple.internal.JAssignStmt; +import soot.jimple.internal.JimpleLocal; import soot.jimple.toolkits.callgraph.CallGraph; import soot.jimple.toolkits.callgraph.Edge; import soot.toolkits.scalar.ArraySparseSet; import soot.toolkits.scalar.FlowSet; +import soot.util.Chain; import java.util.*; import java.util.logging.Level; @@ -23,6 +26,7 @@ // TODO Do not add anything when assignments are equal. public class InterproceduralOverrideAssignment extends SceneTransformer implements AbstractAnalysis { + private int depthLimit; private Set conflicts; private PointsToAnalysis pointsToAnalysis; private List traversedMethods; @@ -31,11 +35,23 @@ public class InterproceduralOverrideAssignment extends SceneTransformer implemen private FlowSet right; private List stacktraceList; - private final Logger logger; + private Logger logger; public InterproceduralOverrideAssignment(AbstractMergeConflictDefinition definition) { this.definition = definition; + this.depthLimit = 10; + initDefaultFields(); + } + + public InterproceduralOverrideAssignment(AbstractMergeConflictDefinition definition, int depthLimit) { + this.definition = definition; + this.depthLimit = depthLimit; + + initDefaultFields(); + } + + private void initDefaultFields() { this.conflicts = new HashSet<>(); this.left = new ArraySparseSet<>(); this.right = new ArraySparseSet<>(); @@ -57,53 +73,67 @@ public Set getConflicts() { return conflicts; } - public void configureEntryPoints() { - definition.loadSourceStatements(); - definition.loadSinkStatements(); - - List entryPoints = new ArrayList<>(); - definition.getSourceStatements().forEach(s -> { - if (!entryPoints.contains(s.getSootMethod())) { - entryPoints.add(s.getSootMethod()); - } - }); - Scene.v().setEntryPoints(entryPoints); - } - @Override protected void internalTransform(String s, Map map) { + long startTime = System.currentTimeMillis(); List methods = Scene.v().getEntryPoints(); methods.forEach(sootMethod -> traverse(new ArraySparseSet<>(), sootMethod, Statement.Type.IN_BETWEEN)); Set conflictsFilter = filterConflicts(getConflicts()); - conflictsFilter.forEach(conflict -> logger.log(Level.INFO, conflict.toStringAbstract())); + logger.log(Level.INFO, () -> String.format("%s", "CONFLICTS: " + conflictsFilter)); - //logger.log(Level.INFO, () -> String.format("%s", "CONFLICTS: " + conflictsFilter)); + long finalTime = System.currentTimeMillis(); + System.out.println("Runtime: " + ((finalTime - startTime) / 1000d) + "s"); + } - /* left.forEach(dataFlowAbstraction -> { - String leftStmt = String.format("%s", "LEFT: " + dataFlowAbstraction.getStmt()); - logger.log(Level.INFO, leftStmt); - }); + public void configureEntryPoints() { + List entryPoints = new ArrayList<>(); + + definition.loadSourceStatements(); + definition.loadSinkStatements(); + + SootMethod sm = getTraversedMethod(); + + if (sm != null) { + entryPoints.add(sm); + } else { + definition.getSourceStatements().forEach(s -> { + if (!entryPoints.contains(s.getSootMethod())) { + entryPoints.add(s.getSootMethod()); + } + }); + } + Scene.v().setEntryPoints(entryPoints); + } - right.forEach(dataFlowAbstraction -> { - String rightStmt = String.format("%s", "RIGHT: " + dataFlowAbstraction.getStmt()); - logger.log(Level.INFO, rightStmt); - }); */ + private SootMethod getTraversedMethod() { + try { + SootClass sootClass = definition.getSourceStatements().get(0).getSootClass(); + return sootClass.getMethodByName("callRealisticRun"); + } catch (RuntimeException e) { + return null; + } } private Set filterConflicts(Set conflictsResults) { Set conflictsFilter = new HashSet<>(); - conflictsResults.forEach(conflict -> { + for (Conflict conflict : conflictsResults) { if (conflictsFilter.isEmpty()) { conflictsFilter.add(conflict); } - conflictsFilter.forEach(filter -> { - if ((!conflict.getSourceTraversedLine().get(0).equals(filter.getSourceTraversedLine().get(0))) && (!conflict.getSinkTraversedLine().get(0).equals(filter.getSinkTraversedLine().get(0)))) { - conflictsFilter.add(conflict); + } + for (Conflict conflict : conflictsResults) { + for (Conflict filter : conflictsFilter) { + if (!conflict.getSourceTraversedLine().isEmpty() && !conflict.getSinkTraversedLine().isEmpty()) { + if ((!conflict.getSourceTraversedLine().get(0).equals(filter.getSourceTraversedLine().get(0))) + && (!conflict.getSinkTraversedLine().get(0).equals(filter.getSinkTraversedLine().get(0)))) { + conflictsFilter.add(conflict); + } } - }); - }); + + } + } return conflictsFilter; } @@ -118,16 +148,18 @@ private Set filterConflicts(Set conflictsResults) { */ private FlowSet traverse(FlowSet in, SootMethod sootMethod, Statement.Type flowChangeTag) { - //System.out.println(sootMethod); - if (this.traversedMethods.contains(sootMethod) || sootMethod.isPhantom()) { + + if (this.traversedMethods.contains(sootMethod) || this.traversedMethods.size() > depthLimit || sootMethod.isPhantom()) { return in; } + System.out.println(sootMethod + " - " + this.traversedMethods.size()); this.traversedMethods.add(sootMethod); Body body = definition.retrieveActiveBodySafely(sootMethod); if (body != null) { + handleConstructor(in, sootMethod, flowChangeTag); for (Unit unit : body.getUnits()) { TraversedLine traversedLine = new TraversedLine(sootMethod, unit.getJavaSourceStartLineNumber()); @@ -146,6 +178,41 @@ private FlowSet traverse(FlowSet in, S return in; } + private void handleConstructor(FlowSet in, SootMethod sootMethod, + Statement.Type flowChangeTag) { + if (sootMethod.isConstructor()) { + Chain sootFieldsInClass = sootMethod.getDeclaringClass().getFields(); + + sootFieldsInClass.forEach(sootField -> { + trasformFieldsIntoStatements(in, sootMethod, flowChangeTag, sootField); + }); + } + } + + private void trasformFieldsIntoStatements(FlowSet in, SootMethod sootMethod, Statement.Type flowChangeTag, SootField sootField) { + String declaringClassShortName = sootField.getDeclaringClass().getShortName(); + String formatName = + declaringClassShortName.substring(0, 1).toLowerCase() + declaringClassShortName.substring(1); + + JimpleLocal base = new JimpleLocal(formatName, RefType.v(sootField.getDeclaringClass())); + SootFieldRef fieldRef = Scene.v().makeFieldRef(sootField.getDeclaringClass(), + sootField.getName(), sootField.getType(), sootField.isStatic()); + + Value value = getValue(base, fieldRef); + Unit unit = new JAssignStmt(value, NullConstant.v()); + createAndAddStmt(in, sootMethod, flowChangeTag, unit); + + } + + private Value getValue(JimpleLocal base, SootFieldRef fieldRef) { + Value value; + if (fieldRef.isStatic()) { + value = Jimple.v().newStaticFieldRef(fieldRef); + } else { + value = Jimple.v().newInstanceFieldRef(base, fieldRef); + } + return value; + } private FlowSet runAnalysisWithTaggedUnit(FlowSet in, SootMethod sootMethod, Statement.Type flowChangeTag, Unit unit) { @@ -185,10 +252,7 @@ private FlowSet runAnalysis(FlowSet in separeteAbstraction(in); if (tagged) { - Statement stmt = getStatementAssociatedWithUnit(sootMethod, unit, flowChangeTag); - stmt.setTraversedLine(new ArrayList<>(this.stacktraceList)); - // logger.log(Level.INFO, () -> String.format("%s", "stmt: " + stmt.toString())); - gen(in, stmt); + createAndAddStmt(in, sootMethod, flowChangeTag, unit); } else { kill(in, unit); } @@ -217,6 +281,12 @@ In this case, this condition will be executed for the call to the foo() method a return in; } + private void createAndAddStmt(FlowSet in, SootMethod sootMethod, Statement.Type flowChangeTag, Unit unit) { + Statement stmt = getStatementAssociatedWithUnit(sootMethod, unit, flowChangeTag); + stmt.setTraversedLine(new ArrayList<>(this.stacktraceList)); + gen(in, stmt); + } + private void separeteAbstraction(FlowSet in) { in.forEach(item -> { if (item.getStmt().isLefAndRightStatement()) { @@ -247,11 +317,16 @@ private FlowSet executeCallGraph(FlowSet flowSetUnion = new ArraySparseSet<>(); for (FlowSet flowSet : flowSetList) { flowSetUnion.union(flowSet); } + if (flowSetUnion.isEmpty()) { + return in; + } + return flowSetUnion; } @@ -326,11 +401,6 @@ private void removeAll(ValueBox valueBox, FlowSet rightOrLe rightOrLeftList.forEach(dataFlowAbstraction -> { try { if (containsValue(dataFlowAbstraction, valueBox.getValue())) { - rightOrLeftList.forEach(dt -> { - if (dt.getStmt().getSourceCodeLineNumber().equals(dataFlowAbstraction.getStmt().getSourceCodeLineNumber())) { - rightOrLeftList.remove(dt); - } - }); rightOrLeftList.remove(dataFlowAbstraction); } } catch (ValueNotHandledException e) { @@ -341,7 +411,7 @@ private void removeAll(ValueBox valueBox, FlowSet rightOrLe private boolean containsValue(DataFlowAbstraction dataFlowAbstraction, Value value) throws ValueNotHandledException { if (dataFlowAbstraction.getValue() instanceof InstanceFieldRef && value instanceof InstanceFieldRef) { - return ((InstanceFieldRef) dataFlowAbstraction.getValue()).getFieldRef().equals(((InstanceFieldRef) value).getFieldRef()); + return ((InstanceFieldRef) dataFlowAbstraction.getValue()).getFieldRef().getSignature().equals(((InstanceFieldRef) value).getFieldRef().getSignature()); } if (dataFlowAbstraction.getValue() instanceof Local && value instanceof Local) { return dataFlowAbstraction.getValue().equals(value); @@ -350,7 +420,7 @@ private boolean containsValue(DataFlowAbstraction dataFlowAbstraction, Value val return dataFlowAbstraction.getValue().equals(value); } if (dataFlowAbstraction.getValue() instanceof StaticFieldRef && value instanceof StaticFieldRef) { - return ((StaticFieldRef) dataFlowAbstraction.getValue()).getField().getName().equals(((StaticFieldRef) value).getField().getName()); + return ((StaticFieldRef) dataFlowAbstraction.getValue()).getFieldRef().getSignature().equals(((StaticFieldRef) value).getFieldRef().getSignature()); } if (!dataFlowAbstraction.getValue().getClass().equals(value.getClass())) { return false; diff --git a/src/main/java/br/unb/cic/analysis/model/Conflict.java b/src/main/java/br/unb/cic/analysis/model/Conflict.java index fcedbbcf..d73c1e8c 100644 --- a/src/main/java/br/unb/cic/analysis/model/Conflict.java +++ b/src/main/java/br/unb/cic/analysis/model/Conflict.java @@ -110,11 +110,17 @@ public int hashCode() { public String toStringAbstract() { - return String.format("source(%s, %s, %d, %s, %s) => sink(%s, %s, %d, %s, %s)", sourceTraversedLine.get(0).getSootClass(), - sourceTraversedLine.get(0).getSootMethod(), sourceTraversedLine.get(0).getLineNumber(), sourceUnit, + if (!sourceTraversedLine.isEmpty() && !sinkTraversedLine.isEmpty()) { + return String.format("source(%s, %s, %d, %s, %s) => sink(%s, %s, %d, %s, %s)", sourceTraversedLine.get(0).getSootClass(), + sourceTraversedLine.get(0).getSootMethod(), sourceTraversedLine.get(0).getLineNumber(), sourceUnit, + sourceTraversedLine, + sinkTraversedLine.get(0).getSootClass(), sinkTraversedLine.get(0).getSootMethod(), + sinkTraversedLine.get(0).getLineNumber(), sinkUnit, sinkTraversedLine); + } + return String.format("source(%s, %s) => sink(%s, %s)", sourceUnit, sourceTraversedLine, - sinkTraversedLine.get(0).getSootClass(), sinkTraversedLine.get(0).getSootMethod(), - sinkTraversedLine.get(0).getLineNumber(), sinkUnit, sinkTraversedLine); + sinkUnit, sinkTraversedLine); + } diff --git a/src/test/java/br/unb/cic/analysis/ioa/InterproceduralOverridingAssignmentAnalysisTest.java b/src/test/java/br/unb/cic/analysis/ioa/InterproceduralOverridingAssignmentAnalysisTest.java index c06fa40b..72687456 100644 --- a/src/test/java/br/unb/cic/analysis/ioa/InterproceduralOverridingAssignmentAnalysisTest.java +++ b/src/test/java/br/unb/cic/analysis/ioa/InterproceduralOverridingAssignmentAnalysisTest.java @@ -28,7 +28,7 @@ private void configureTest(InterproceduralOverrideAssignment analysis) { analysis.configureEntryPoints(); PackManager.v().getPack("wjtp").add(new Transform("wjtp.analysis", analysis)); - SootWrapper.configurePackagesWithCallGraph().forEach(p -> PackManager.v().getPack(p).apply()); + SootWrapper.applyPackages(); try { exportResults(analysis.getConflicts()); @@ -66,10 +66,30 @@ private void exportResults(Set conflicts) throws Exception { } @Test - public void StringArraySample() { + public void loggingTest() { + String sampleClassPath = "br.unb.cic.analysis.samples.ioa.LoggingConflictSample"; + AbstractMergeConflictDefinition definition = DefinitionFactory + .definition(sampleClassPath, new int[]{13}, new int[]{10}); + InterproceduralOverrideAssignment analysis = new InterproceduralOverrideAssignment(definition); + configureTest(analysis); + Assert.assertEquals(1, analysis.getConflicts().size()); + } + + @Test + public void defaultConstructorTest() { + String sampleClassPath = "br.unb.cic.analysis.samples.ioa.DefaultConstructorConflictSample"; + AbstractMergeConflictDefinition definition = DefinitionFactory + .definition(sampleClassPath, new int[]{12}, new int[]{14}); + InterproceduralOverrideAssignment analysis = new InterproceduralOverrideAssignment(definition); + configureTest(analysis); + Assert.assertEquals(1, analysis.getConflicts().size()); + } + + @Test + public void StringArrayTest() { String sampleClassPath = "br.unb.cic.analysis.samples.ioa.StringArraySample"; AbstractMergeConflictDefinition definition = DefinitionFactory - .definition(sampleClassPath, new int[]{11}, new int[]{22}); + .definition(sampleClassPath, new int[]{14}, new int[]{25}); InterproceduralOverrideAssignment analysis = new InterproceduralOverrideAssignment(definition); configureTest(analysis); Assert.assertEquals(1, analysis.getConflicts().size()); diff --git a/src/test/java/br/unb/cic/analysis/samples/ioa/DefaultConstructorConflictSample.java b/src/test/java/br/unb/cic/analysis/samples/ioa/DefaultConstructorConflictSample.java new file mode 100644 index 00000000..a7b303f5 --- /dev/null +++ b/src/test/java/br/unb/cic/analysis/samples/ioa/DefaultConstructorConflictSample.java @@ -0,0 +1,15 @@ +package br.unb.cic.analysis.samples.ioa; + +public class DefaultConstructorConflictSample { + private static int x; + + public DefaultConstructorConflictSample() { + + } + + public void m() { + DefaultConstructorConflictSample defaultConstructorConflictSample = new DefaultConstructorConflictSample(); + int y = 2; + defaultConstructorConflictSample.x = 1; + } +} \ No newline at end of file diff --git a/src/test/java/br/unb/cic/analysis/samples/ioa/LoggingConflictSample.java b/src/test/java/br/unb/cic/analysis/samples/ioa/LoggingConflictSample.java new file mode 100644 index 00000000..775423d8 --- /dev/null +++ b/src/test/java/br/unb/cic/analysis/samples/ioa/LoggingConflictSample.java @@ -0,0 +1,17 @@ +package br.unb.cic.analysis.samples.ioa; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +public class LoggingConflictSample { + private final Log logger = LogFactory.getLog(getClass()); + + public void logAutoConfigurationReport() { + this.logger.info("Error starting ApplicationContext."); + + if (this.logger.isDebugEnabled()) { + this.logger.debug("Unable to provide auto-configuration report"); + } + } + +}