+ * Represents a control flow graph for a {@link Body} instance where the nodes are {@link Unit} instances, and where control + * flow associated with exceptions is taken into account. + *
+ * + *
+ * To describe precisely the circumstances under which exceptional edges are added to the graph, we need to distinguish the
+ * exceptions thrown explicitly by a throw instruction from the exceptions which are thrown implicitly by the VM
+ * to signal an error it encounters in the course of executing an instruction, which need not be a throw.
+ *
+ * For every {@link ThrowInst} or {@link ThrowStmt} Unit which may explicitly throw an exception that would be
+ * caught by a {@link Trap} in the Body, there will be an edge from the throw Unit to
+ * the Trap handler's first Unit.
+ *
+ * For every Unit which may implicitly throw an exception that could be caught by a Trap in the
+ * Body, there will be an edge from each of the excepting Unit's predecessors to the
+ * Trap handler's first Unit (since any of those predecessors may have been the last
+ * Unit to complete execution before the handler starts execution). If the excepting Unit might
+ * have the side effect of changing some field, then there will definitely be an edge from the excepting Unit
+ * itself to its handlers, since the side effect might occur before the exception is raised. If the excepting
+ * Unit has no side effects, then parameters passed to the ExceptionalUnitGraph constructor
+ * determine whether or not there is an edge from the excepting Unit itself to the handler Unit.
+ *
+ * Represents a control flow graph for a {@link Body} instance where the nodes are {@link Unit} instances, and where control + * flow associated with exceptions is taken into account. + *
+ * + *
+ * To describe precisely the circumstances under which exceptional edges are added to the graph, we need to distinguish the
+ * exceptions thrown explicitly by a throw instruction from the exceptions which are thrown implicitly by the VM
+ * to signal an error it encounters in the course of executing an instruction, which need not be a throw.
+ *
+ * For every {@link ThrowInst} or {@link ThrowStmt} Unit which may explicitly throw an exception that would be
+ * caught by a {@link Trap} in the Body, there will be an edge from the throw Unit to
+ * the Trap handler's first Unit.
+ *
+ * For every Unit which may implicitly throw an exception that could be caught by a Trap in the
+ * Body, there will be an edge from each of the excepting Unit's predecessors to the
+ * Trap handler's first Unit (since any of those predecessors may have been the last
+ * Unit to complete execution before the handler starts execution). If the excepting Unit might
+ * have the side effect of changing some field, then there will definitely be an edge from the excepting Unit
+ * itself to its handlers, since the side effect might occur before the exception is raised. If the excepting
+ * Unit has no side effects, then parameters passed to the ExceptionalUnitGraph constructor
+ * determine whether or not there is an edge from the excepting Unit itself to the handler Unit.
+ *
+ * Represents a control flow graph for a {@link Body} instance where the nodes are {@link Unit} instances, and where control + * flow associated with exceptions is taken into account. + *
+ * + *
+ * To describe precisely the circumstances under which exceptional edges are added to the graph, we need to distinguish the
+ * exceptions thrown explicitly by a throw instruction from the exceptions which are thrown implicitly by the VM
+ * to signal an error it encounters in the course of executing an instruction, which need not be a throw.
+ *
+ * For every {@link ThrowInst} or {@link ThrowStmt} Unit which may explicitly throw an exception that would be
+ * caught by a {@link Trap} in the Body, there will be an edge from the throw Unit to
+ * the Trap handler's first Unit.
+ *
+ * For every Unit which may implicitly throw an exception that could be caught by a Trap in the
+ * Body, there will be an edge from each of the excepting Unit's predecessors to the
+ * Trap handler's first Unit (since any of those predecessors may have been the last
+ * Unit to complete execution before the handler starts execution). If the excepting Unit might
+ * have the side effect of changing some field, then there will definitely be an edge from the excepting Unit
+ * itself to its handlers, since the side effect might occur before the exception is raised. If the excepting
+ * Unit has no side effects, then parameters passed to the ExceptionalUnitGraph constructor
+ * determine whether or not there is an edge from the excepting Unit itself to the handler Unit.
+ *
ThrowAnalysis and
+ * omitExceptingUnitEdges value that are passed as parameters.
+ *
+ * @param body
+ * the Body from which to build a graph.
+ *
+ * @param throwAnalysis
+ * the source of information about the exceptions which each {@link Unit} may throw.
+ *
+ * @param omitExceptingUnitEdges
+ * indicates whether the CFG should omit edges to a handler from trapped Units which may implicitly
+ * throw an exception which the handler catches but which have no potential side effects. The CFG will contain
+ * edges to the handler from all predecessors of Units which may implicitly throw a caught exception
+ * regardless of the setting for this parameter. If this parameter is false, there will also be edges
+ * to the handler from all the potentially excepting Units themselves. If this parameter is
+ * true, there will be edges to the handler from the excepting Units themselves only if
+ * they have potential side effects (or if they are themselves the predecessors of other potentially excepting
+ * Units). A setting of true produces CFGs which allow for more precise analyses, since
+ * a Unit without side effects has no effect on the computational state when it throws an exception.
+ * Use settings of false for compatibility with more conservative analyses, or to cater to
+ * conservative bytecode verifiers.
+ */
+ public UnitGraphNodes(Body body, ThrowAnalysis throwAnalysis, boolean omitExceptingUnitEdges) {
+ super(body);
+ initialize(throwAnalysis, omitExceptingUnitEdges);
+ }
+
+ /**
+ * Constructs the graph from a given Body instance using the passed {@link ThrowAnalysis} and a default value, provided by
+ * the {@link Options} class, for the omitExceptingUnitEdges parameter.
+ *
+ * @param body
+ * the {@link Body} from which to build a graph.
+ *
+ * @param throwAnalysis
+ * the source of information about the exceptions which each {@link Unit} may throw.
+ *
+ */
+ public UnitGraphNodes(Body body, ThrowAnalysis throwAnalysis) {
+ this(body, throwAnalysis, Options.v().omit_excepting_unit_edges());
+ }
+
+ /**
+ * Constructs the graph from a given Body instance, using the {@link Scene} 's default {@link ThrowAnalysis} to estimate
+ * the set of exceptions that each {@link Unit} might throw and a default value, provided by the {@link Options} class, for
+ * the omitExceptingUnitEdges parameter.
+ *
+ * @param body
+ * the Body from which to build a graph.
+ *
+ */
+ public UnitGraphNodes(Body body) {
+ this(body, Scene.v().getDefaultThrowAnalysis(), Options.v().omit_excepting_unit_edges());
+ }
+
+ /**
+ *
+ * Allocates an ExceptionalUnitGraph object without initializing it. This “partial constructor” is
+ * provided for the benefit of subclasses whose constructors need to perform some subclass-specific processing before
+ * actually creating the graph edges (because, for example, the subclass overrides a utility method like
+ * {@link #buildExceptionDests(ThrowAnalysis)} or {@link #buildExceptionalEdges(ThrowAnalysis, Map, Map, Map, boolean)}
+ * with a replacement method that depends on additional parameters passed to the subclass's constructor). The subclass
+ * constructor is responsible for calling {@link #initialize(ThrowAnalysis, boolean)}, or otherwise performing the
+ * initialization required to implement ExceptionalUnitGraph's interface.
+ *
+ * Clients who opt to extend ExceptionalUnitGraph should be warned that the class has not been carefully
+ * designed for inheritance; code that uses the protected members of this class may need to be rewritten for
+ * each new Soot release.
+ *
Body from which to build a graph.
+ *
+ * @param ignoredBogusParameter
+ * a meaningless placeholder, which exists solely to distinguish this constructor from the public
+ * {@link #ExceptionalUnitGraph(Body)} constructor.
+ */
+ protected UnitGraphNodes(Body body, boolean ignoredBogusParameter) {
+ super(body);
+ }
+
+ /**
+ * Performs the real work of constructing an ExceptionalUnitGraph, factored out of the constructors so that
+ * subclasses have the option to delay creating the graph's edges until after they have performed some subclass-specific
+ * initialization.
+ *
+ * @param throwAnalysis
+ * the source of information about the exceptions which each {@link Unit} may throw.
+ *
+ * @param omitExceptingUnitEdges
+ * indicates whether the CFG should omit edges to a handler from trapped Units which may throw an
+ * exception which the handler catches but which have no potential side effects.
+ */
+ protected void initialize(ThrowAnalysis throwAnalysis, boolean omitExceptingUnitEdges) {
+ int size = unitChain.size();
+ Set+ * Utility method used in the construction of {@link soot.toolkits.graph.UnitGraph UnitGraph} variants which include + * exceptional control flow. It determines which {@link Unit}s may throw exceptions that would be caught by {@link Trap}s + * within the method. + *
+ * + * @param throwAnalysis + * The source of information about which exceptions eachUnit may throw.
+ *
+ * @return null if no Units in the method throw any exceptions caught within the method.
+ * Otherwise, a {@link Map} from Units to {@link Collection}s of {@link ExceptionDest}s.
+ *
+ *
+ * The returned map has an idiosyncracy which is hidden from most client code, but which is exposed to subclasses
+ * extending ExceptionalUnitGraph. If a Unit throws one or more exceptions which are
+ * caught within the method, it will be mapped to a Collection of ExceptionDests
+ * describing the sets of exceptions that the Unit might throw to each {@link Trap}. But if all of a
+ * Unit's exceptions escape the method, it will be mapped to nullCollection containing a single ExceptionDest with a null trap. (The
+ * special case for Units with no caught exceptions allows buildExceptionDests() to
+ * ignore completely Units which are outside the scope of all Traps.)
+ *
Unit throws to a particular Trap. Note
+ * that this method relies on the fact that the call to add escaping exceptions for a Unit will always follow
+ * all calls for its caught exceptions.
+ *
+ * @param map
+ * A Map from Units to Collections of ExceptionDests.
+ * null if no exceptions have been recorded yet.
+ *
+ * @param u
+ * The Unit throwing the exceptions.
+ *
+ * @param t
+ * The Trap which catches the exceptions, or null if the exceptions escape the method.
+ *
+ * @param caught
+ * The set of exception types thrown by u which are caught by t.
+ *
+ * @return a Map which whose contents are equivalent to the input map, plus the information that
+ * u throws caught to t.
+ */
+ private MapMap from {@link Unit}s to {@link Collection}s of {@link ExceptionalUnitGraph.ExceptionDest
+ * ExceptionDest}s which represent the handlers that might catch exceptions thrown by the Unit. This
+ * is an ``in parameter''.
+ *
+ * @param unitToSuccs
+ * A Map from Units to {@link List}s of Units. This is an ``out
+ * parameter''; buildExceptionalEdges will add a mapping from every Unit in the body
+ * that may throw an exception that could be caught by a {@link Trap} in the body to a list of its exceptional
+ * successors.
+ *
+ * @param unitToPreds
+ * A Map from Units to Lists of Units. This is an ``out
+ * parameter''; buildExceptionalEdges will add a mapping from each handler unit that may catch an
+ * exception to the list of Units whose exceptions it may catch.
+ * @param omitExceptingUnitEdges
+ * Indicates whether to omit exceptional edges from excepting units which lack side effects
+ *
+ * @return a {@link Set} of trap Units that might catch exceptions thrown by the first Unit in
+ * the {@link Body} associated with the graph being constructed. Such trap Units may need to be added
+ * to the list of heads (depending on your definition of heads), since they can be the first Unit in
+ * the Body which actually completes execution.
+ */
+ protected Set+ * Utility method for checking if a {@link Unit} might have side effects. It simply returns true for any unit which invokes + * a method directly or which might invoke static initializers indirectly (by creating a new object or by refering to a + * static field; see sections 2.17.4, 2.17.5, and 5.5 of the Java Virtual Machine Specification). + *
+ * + *mightHaveSideEffects() is declared package-private so that it is available to unit tests that are part of
+ * this package.
+ *
+ * @param u
+ * The unit whose potential for side effects is to be checked.
+ *
+ * @return whether or not u has the potential for side effects.
+ */
+ static boolean mightHaveSideEffects(Unit u) {
+ if (u instanceof Inst) {
+ Inst i = (Inst) u;
+ return (i.containsInvokeExpr() || (i instanceof StaticPutInst) || (i instanceof StaticGetInst)
+ || (i instanceof NewInst));
+ } else if (u instanceof Stmt) {
+ for (ValueBox vb : u.getUseBoxes()) {
+ Value v = vb.getValue();
+ if ((v instanceof StaticFieldRef) || (v instanceof InvokeExpr) || (v instanceof NewExpr)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Utility method for checking if a Unit might throw an exception which may be caught by a {@link Trap} within this method.
+ *
+ * @param u
+ * The unit for whose exceptions are to be checked
+ *
+ * @return whether or not u may throw an exception which may be caught by a Trap in this method,
+ */
+ private boolean mightThrowToIntraproceduralCatcher(Unit u) {
+ Collection
+ * A placeholder that overrides {@link UnitGraph#buildHeadsAndTails()} with a method which always throws an exception. The
+ * placeholder serves to indicate that ExceptionalUnitGraph does not use buildHeadsAndTails(),
+ * and to document the conditions under which ExceptionalUnitGraph considers a node to be a head or
+ * tail.
+ *
+ * ExceptionalUnitGraph defines the graph's set of heads to include the first {@link Unit} in the graph's
+ * body, together with the first Unit in any exception handler which might catch an exception thrown by the
+ * first Unit in the body (because any of those Units might be the first to successfully complete
+ * execution). ExceptionalUnitGraph defines the graph's set of tails to include all Units which
+ * represent some variety of return bytecode or an athrow bytecode whose argument might escape the method.
+ *
Units in
+ * additionalHeads. It defines the graph's set of tails to include all Units which represent some
+ * sort of return bytecode or an athrow bytecode which may escape the method.
+ */
+ private void buildHeadsAndTails(Setu must be a Unit, though the
+ * parameter is declared as an Object to satisfy the interface of
+ * {@link soot.toolkits.graph.ExceptionalGraph ExceptionalGraph}.
+ *
+ * @return a collection of ExceptionDest objects describing the traps, if any, which catch the exceptions
+ * which may be thrown by u.
+ */
+ @Override
+ public Collection
+ * Return the {@link ThrowAnalysis} used to construct this graph, if the graph contains no {@link Trap}s, or
+ * null if the graph does contain Traps. A reference to the ThrowAnalysis is kept
+ * when there are no Traps so that the graph can generate responses to {@link #getExceptionDests(Object)} on
+ * the fly, rather than precomputing information that may never be needed.
+ *
+ * This method is package-private because it exposes a detail of the implementation of ExceptionalUnitGraph so
+ * that the {@link soot.toolkits.graph.ExceptionalBlockGraph ExceptionalBlockGraph} constructor can cache the same
+ * ThrowAnalysis for the same purpose.
+ *
+ * @return the {@link ThrowAnalysis} used to generate this graph if the graph contains no {@link Trap}s, or
+ * null if the graph contains one or more {@link Trap}s.
+ */
+ ThrowAnalysis getThrowAnalysis() {
+ return throwAnalysis;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (Unit u : unitChain) {
+ buf.append(" preds: " + getPredsOf(u) + "\n");
+ buf.append(" unexceptional preds: " + getUnexceptionalPredsOf(u) + "\n");
+ buf.append(" exceptional preds: " + getExceptionalPredsOf(u) + "\n");
+ buf.append(u.toString() + '\n');
+ buf.append(" exception destinations: " + getExceptionDests(u) + "\n");
+ buf.append(" unexceptional succs: " + getUnexceptionalSuccsOf(u) + "\n");
+ buf.append(" exceptional succs: " + getExceptionalSuccsOf(u) + "\n");
+ buf.append(" succs " + getSuccsOf(u) + "\n\n");
+ }
+
+ return buf.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/samples/BlackBoard.java b/src/test/java/samples/BlackBoard.java
index ce344fa..3702f57 100644
--- a/src/test/java/samples/BlackBoard.java
+++ b/src/test/java/samples/BlackBoard.java
@@ -1,17 +1,18 @@
package samples;
public class BlackBoard {
- public static String text = "";
- public static void main(){
- if (text != "" && hasWhiteSpace()){
- normalizeWhiteSpace();
- removeDuplicateWords();
+ public static void main() throws Exception{
+ try {
+ int x = 0; //source
+ if (x==0){
+ x = x + 1;
+ }
+ x = x + 2; //sink
+ }
+ finally {
+ System.out.println("Message");
}
}
- public static void normalizeWhiteSpace(){};
- public static boolean hasWhiteSpace(){
- return true;
- };
- public static void removeDuplicateWords(){};
+
}
\ No newline at end of file
diff --git a/src/test/java/samples/OneDoWhileAndOneIf.java b/src/test/java/samples/OneDoWhileAndOneIf.java
index 08b5275..54bbb32 100644
--- a/src/test/java/samples/OneDoWhileAndOneIf.java
+++ b/src/test/java/samples/OneDoWhileAndOneIf.java
@@ -5,10 +5,10 @@ public static void main() {
do{
x = 2;
if (x == 0){
- x = 3;
+ x = 3; //source
}
x = 5;
- }while (x < 1);
+ }while (x < 1); //sink
x = 4;
}
}
\ No newline at end of file
diff --git a/src/test/java/samples/OneReturnZeroConflict.java b/src/test/java/samples/OneReturnZeroConflict.java
new file mode 100644
index 0000000..bd7f55f
--- /dev/null
+++ b/src/test/java/samples/OneReturnZeroConflict.java
@@ -0,0 +1,10 @@
+package samples;
+public class OneReturnZeroConflict {
+ public static int main(){
+ int x = 0;
+ if (x==1){ //source
+ x = 1;
+ }
+ return x; //sink
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/samples/TwoReturnOneConflict.java b/src/test/java/samples/TwoReturnOneConflict.java
new file mode 100644
index 0000000..904c77b
--- /dev/null
+++ b/src/test/java/samples/TwoReturnOneConflict.java
@@ -0,0 +1,10 @@
+package samples;
+public class TwoReturnOneConflict {
+ public static int main(){
+ int x = 0;
+ if (x==1){ //source
+ return 1;
+ }
+ return x; //sink
+ }
+}
\ No newline at end of file
diff --git a/src/test/scala/br/ufpe/cin/soot/OneReturnZeroConflictTest.scala b/src/test/scala/br/ufpe/cin/soot/OneReturnZeroConflictTest.scala
new file mode 100644
index 0000000..273ce59
--- /dev/null
+++ b/src/test/scala/br/ufpe/cin/soot/OneReturnZeroConflictTest.scala
@@ -0,0 +1,45 @@
+package br.ufpe.cin.soot
+
+import br.ufpe.cin.soot.graph.{NodeType, SimpleNode, SinkNode, SourceNode}
+import soot.jimple.{AssignStmt, InvokeExpr, InvokeStmt}
+
+class OneReturnZeroConflictTest(leftchangedlines: Array[Int], rightchangedlines: Array[Int]) extends JCDATest {
+ override def getClassName(): String = "samples.OneReturnZeroConflict"
+ override def getMainMethod(): String = "main"
+
+ def this(){
+ this(Array.empty[Int], Array.empty[Int])
+ }
+
+ override def analyze(unit: soot.Unit): NodeType = {
+
+ if (!leftchangedlines.isEmpty && !rightchangedlines.isEmpty){
+ if (leftchangedlines.contains(unit.getJavaSourceStartLineNumber)){
+ return SourceNode
+ } else if (rightchangedlines.contains(unit.getJavaSourceStartLineNumber)){
+ return SinkNode
+ }
+ }
+
+ if(unit.isInstanceOf[InvokeStmt]) {
+ val invokeStmt = unit.asInstanceOf[InvokeStmt]
+ return analyzeInvokeStmt(invokeStmt.getInvokeExpr)
+ }
+ if(unit.isInstanceOf[soot.jimple.AssignStmt]) {
+ val assignStmt = unit.asInstanceOf[AssignStmt]
+ if(assignStmt.getRightOp.isInstanceOf[InvokeExpr]) {
+ val invokeStmt = assignStmt.getRightOp.asInstanceOf[InvokeExpr]
+ return analyzeInvokeStmt(invokeStmt)
+ }
+ }
+ return SimpleNode
+ }
+
+ def analyzeInvokeStmt(exp: InvokeExpr) : NodeType =
+ exp.getMethod.getName match {
+ case "source" => SourceNode
+ case "sink" => SinkNode
+ case _ => SimpleNode
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/scala/br/ufpe/cin/soot/TestSuite.scala b/src/test/scala/br/ufpe/cin/soot/TestSuite.scala
index 5707ae2..3ae95ff 100644
--- a/src/test/scala/br/ufpe/cin/soot/TestSuite.scala
+++ b/src/test/scala/br/ufpe/cin/soot/TestSuite.scala
@@ -1,15 +1,11 @@
package br.ufpe.cin.soot
-import br.ufpe.cin.soot.graph.{Graph, LambdaNode}
import org.scalatest.{BeforeAndAfter, FunSuite}
-import scala.collection.mutable.ListBuffer
-
class TestSuite extends FunSuite with BeforeAndAfter {
-
- test("we should correctly compute the number of nodes and edges in the BlackBoardTest sample") {
- val controlDependence = new BlackBoardTest( Array (5), Array (7))
+ test ("we should correctly compute the number of nodes and edges in the BlackBoardTest sample") {
+ val controlDependence = new BlackBoardTest( Array (5), Array (9))
// val controlDependence = new BlackBoardTest()
controlDependence.buildCDA()
var x = controlDependence.findConflictingPaths()
@@ -17,225 +13,235 @@ class TestSuite extends FunSuite with BeforeAndAfter {
println(controlDependence.svgToDotModel())
}
- def thereIsPath(source: ListBuffer[LambdaNode], target: ListBuffer[LambdaNode], graph: Graph): Boolean ={
- var thereIs = false
- source.foreach(s =>{
- target.foreach(t =>{
- val path = graph.findPath(s, t)
- if (path.size>0) {
- println("There is a path from \""+s.show()+"\" to \""+ t.show()+"\"")
- thereIs = true
- }
- })
- })
- return thereIs
+ test ("we should correctly compute the number of conflicts in the OneReturnZeroConflitc sample") {
+ val controlDependence = new OneReturnZeroConflictTest( Array (5), Array (8))
+ controlDependence.buildCDA()
+ var x = controlDependence.findConflictingPaths()
+// println("Conflits: "+controlDependence.findConflictingPaths().size);
+ println(controlDependence.svgToDotModel())
+ assert(controlDependence.findConflictingPaths().size == 0)
+ assert(controlDependence.svg.numberOfNodes() == 6)
+ assert(controlDependence.svg.numberOfEdges() == 5)
+ }
+
+ test ("we should correctly compute the number of conflicts in the TwoReturnOneConflitc sample") {
+ val controlDependence = new TwoReturnOneConflictTest( Array (5), Array (8))
+ controlDependence.buildCDA()
+ var x = controlDependence.findConflictingPaths()
+// println("Conflits: "+controlDependence.findConflictingPaths().size);
+ println(controlDependence.svgToDotModel())
+ assert(controlDependence.findConflictingPaths().size == 1)
+ assert(controlDependence.svg.numberOfNodes() == 6)
+ assert(controlDependence.svg.numberOfEdges() == 5)
}
test("we should correctly compute the number of nodes and edges in the NestedAll1Test sample") {
val controlDependence = new NestedAll1Test()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 18)
- assert(controlDependence.svg.numberOfEdges() == 17)
+ assert(controlDependence.svg.numberOfNodes() == 19)
+ assert(controlDependence.svg.numberOfEdges() == 18)
}
test("we should correctly compute the number of nodes and edges in the NestedAll2Test sample") {
val controlDependence = new NestedAll2Test()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 18)
- assert(controlDependence.svg.numberOfEdges() == 17)
+ assert(controlDependence.svg.numberOfNodes() == 19)
+ assert(controlDependence.svg.numberOfEdges() == 18)
}
test("we should correctly compute the number of nodes and edges in the NestedIfTest sample") {
val controlDependence = new NestedIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 8)
- assert(controlDependence.svg.numberOfEdges() == 7)
+ assert(controlDependence.svg.numberOfNodes() == 9)
+ assert(controlDependence.svg.numberOfEdges() == 8)
}
test("we should correctly compute the number of nodes and edges in the NestedIfElseIfTest sample") {
val controlDependence = new NestedIfElseIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 16)
- assert(controlDependence.svg.numberOfEdges() == 15)
+ assert(controlDependence.svg.numberOfNodes() == 17)
+ assert(controlDependence.svg.numberOfEdges() == 16)
}
test("we should correctly compute the number of nodes and edges in the NestedIfWhileIfElseTest sample") {
val controlDependence = new NestedIfWhileIfElseTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 10)
- assert(controlDependence.svg.numberOfEdges() == 9)
+ assert(controlDependence.svg.numberOfNodes() == 11)
+ assert(controlDependence.svg.numberOfEdges() == 10)
}
test("we should correctly compute the number of nodes and edges in the NestedThreeIfTest sample") {
val controlDependence = new NestedThreeIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 12)
- assert(controlDependence.svg.numberOfEdges() == 11)
+ assert(controlDependence.svg.numberOfNodes() == 13)
+ assert(controlDependence.svg.numberOfEdges() == 12)
}
test("we should correctly compute the number of nodes and edges in the NestedThreeWhileTest sample") {
val controlDependence = new NestedThreeWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 9)
- assert(controlDependence.svg.numberOfEdges() == 8)
+ assert(controlDependence.svg.numberOfNodes() == 10)
+ assert(controlDependence.svg.numberOfEdges() == 9)
}
test("we should correctly compute the number of nodes and edges in the NestedTwoWhileIfTest sample") {
val controlDependence = new NestedTwoWhileIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 10)
- assert(controlDependence.svg.numberOfEdges() == 9)
+ assert(controlDependence.svg.numberOfNodes() == 11)
+ assert(controlDependence.svg.numberOfEdges() == 10)
}
test("we should correctly compute the number of nodes and edges in the NestedWhileAndIfTest sample") {
val controlDependence = new NestedWhileAndIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 12)
- assert(controlDependence.svg.numberOfEdges() == 11)
+ assert(controlDependence.svg.numberOfNodes() == 13)
+ assert(controlDependence.svg.numberOfEdges() == 12)
}
test("we should correctly compute the number of nodes and edges in the NestedWhileDoWhileIfTest sample") {
val controlDependence = new NestedWhileDoWhileIfTest()
controlDependence.buildCDA()
-// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 11)
- assert(controlDependence.svg.numberOfEdges() == 13)
+ println(controlDependence.svgToDotModel())
+ assert(controlDependence.svg.numberOfNodes() == 12)
+ assert(controlDependence.svg.numberOfEdges() == 14)
}
test("we should correctly compute the number of nodes and edges in the NestedWhileIfWhileTest sample") {
val controlDependence = new NestedWhileIfWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 9)
- assert(controlDependence.svg.numberOfEdges() == 8)
+ assert(controlDependence.svg.numberOfNodes() == 10)
+ assert(controlDependence.svg.numberOfEdges() == 9)
}
test("we should correctly compute the number of nodes and edges in the NestedWhileWhileIfWhileTest sample") {
val controlDependence = new NestedWhileWhileIfWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 14)
- assert(controlDependence.svg.numberOfEdges() == 13)
+ assert(controlDependence.svg.numberOfNodes() == 15)
+ assert(controlDependence.svg.numberOfEdges() == 14)
}
test("we should correctly compute the number of nodes and edges in the OneDoWhileAndOneIfElseTest sample") {
val controlDependence = new OneDoWhileAndOneIfElseTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 10)
- assert(controlDependence.svg.numberOfEdges() == 12)
+ assert(controlDependence.svg.numberOfNodes() == 11)
+ assert(controlDependence.svg.numberOfEdges() == 13)
}
test("we should correctly compute the number of nodes and edges in the OneDoWhileAndOneIfTest sample") {
- val controlDependence = new OneDoWhileAndOneIfTest()
+ val controlDependence = new OneDoWhileAndOneIfTest(Array (11), Array (6))
controlDependence.buildCDA()
+// println("Conflits: "+controlDependence.findConflictingPaths().size);
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 9)
- assert(controlDependence.svg.numberOfEdges() == 11)
+ assert(controlDependence.findConflictingPaths().size == 1)
+ assert(controlDependence.svg.numberOfNodes() == 10)
+ assert(controlDependence.svg.numberOfEdges() == 12)
}
test("we should correctly compute the number of nodes and edges in the OneDoWhileAndWhileTest sample") {
val controlDependence = new OneDoWhileAndWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 9)
- assert(controlDependence.svg.numberOfEdges() == 11)
+ assert(controlDependence.svg.numberOfNodes() == 10)
+ assert(controlDependence.svg.numberOfEdges() == 12)
}
test("we should correctly compute the number of nodes and edges in the OneDoWhileTest sample") {
val controlDependence = new OneDoWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 6)
- assert(controlDependence.svg.numberOfEdges() == 6)
+ assert(controlDependence.svg.numberOfNodes() == 7)
+ assert(controlDependence.svg.numberOfEdges() == 7)
}
test("we should correctly compute the number of nodes and edges in the OneForTest sample") {
val controlDependence = new OneForTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 8)
- assert(controlDependence.svg.numberOfEdges() == 7)
+ assert(controlDependence.svg.numberOfNodes() == 9)
+ assert(controlDependence.svg.numberOfEdges() == 8)
}
test("we should correctly compute the number of nodes and edges in the OneIfElseAndOneWhileTest sample") {
val controlDependence = new OneIfElseAndOneWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 10)
- assert(controlDependence.svg.numberOfEdges() == 9)
+ assert(controlDependence.svg.numberOfNodes() == 11)
+ assert(controlDependence.svg.numberOfEdges() == 10)
}
test("we should correctly compute the number of nodes and edges in the OneIfElseTest sample") {
val controlDependence = new OneIfElseTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 7)
- assert(controlDependence.svg.numberOfEdges() == 6)
+ assert(controlDependence.svg.numberOfNodes() == 8)
+ assert(controlDependence.svg.numberOfEdges() == 7)
}
test("we should correctly compute the number of nodes and edges in the OneIfTest sample") {
val controlDependence = new OneIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 6)
- assert(controlDependence.svg.numberOfEdges() == 5)
+ assert(controlDependence.svg.numberOfNodes() == 7)
+ assert(controlDependence.svg.numberOfEdges() == 6)
}
test("we should correctly compute the number of nodes and edges in the OneWhileAndNestedIfElseTest sample") {
val controlDependence = new OneWhileAndNestedIfElseTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 10)
- assert(controlDependence.svg.numberOfEdges() == 9)
+ assert(controlDependence.svg.numberOfNodes() == 11)
+ assert(controlDependence.svg.numberOfEdges() == 10)
}
test("we should correctly compute the number of nodes and edges in the OneWhileAndNestedIfTest sample") {
val controlDependence = new OneWhileAndNestedIfTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 9)
- assert(controlDependence.svg.numberOfEdges() == 8)
+ assert(controlDependence.svg.numberOfNodes() == 10)
+ assert(controlDependence.svg.numberOfEdges() == 9)
}
test("we should correctly compute the number of nodes and edges in the OneWhileAndOneIfElseTest sample") {
val controlDependence = new OneWhileAndOneIfElseTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 10)
- assert(controlDependence.svg.numberOfEdges() == 9)
+ assert(controlDependence.svg.numberOfNodes() == 11)
+ assert(controlDependence.svg.numberOfEdges() == 10)
}
test("we should correctly compute the number of nodes and edges in the OneWhileTest sample") {
val controlDependence = new OneWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 6)
- assert(controlDependence.svg.numberOfEdges() == 5)
+ assert(controlDependence.svg.numberOfNodes() == 7)
+ assert(controlDependence.svg.numberOfEdges() == 6)
}
test("we should correctly compute the number of nodes and edges in the TwoIfElseTest sample") {
val controlDependence = new TwoIfElseTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 11)
- assert(controlDependence.svg.numberOfEdges() == 10)
+ assert(controlDependence.svg.numberOfNodes() == 12)
+ assert(controlDependence.svg.numberOfEdges() == 11)
}
test("we should correctly compute the number of nodes and edges in the WhileIfIfElseDoWhileTest sample") {
val controlDependence = new WhileIfIfElseDoWhileTest()
controlDependence.buildCDA()
// println(controlDependence.svgToDotModel())
- assert(controlDependence.svg.numberOfNodes() == 16)
- assert(controlDependence.svg.numberOfEdges() == 16)
+ assert(controlDependence.svg.numberOfNodes() == 17)
+ assert(controlDependence.svg.numberOfEdges() == 17)
}
}
diff --git a/src/test/scala/br/ufpe/cin/soot/TwoReturnOneConflictTest.scala b/src/test/scala/br/ufpe/cin/soot/TwoReturnOneConflictTest.scala
new file mode 100644
index 0000000..d661b95
--- /dev/null
+++ b/src/test/scala/br/ufpe/cin/soot/TwoReturnOneConflictTest.scala
@@ -0,0 +1,45 @@
+package br.ufpe.cin.soot
+
+import br.ufpe.cin.soot.graph.{NodeType, SimpleNode, SinkNode, SourceNode}
+import soot.jimple.{AssignStmt, InvokeExpr, InvokeStmt}
+
+class TwoReturnOneConflictTest(leftchangedlines: Array[Int], rightchangedlines: Array[Int]) extends JCDATest {
+ override def getClassName(): String = "samples.TwoReturnOneConflict"
+ override def getMainMethod(): String = "main"
+
+ def this(){
+ this(Array.empty[Int], Array.empty[Int])
+ }
+
+ override def analyze(unit: soot.Unit): NodeType = {
+
+ if (!leftchangedlines.isEmpty && !rightchangedlines.isEmpty){
+ if (leftchangedlines.contains(unit.getJavaSourceStartLineNumber)){
+ return SourceNode
+ } else if (rightchangedlines.contains(unit.getJavaSourceStartLineNumber)){
+ return SinkNode
+ }
+ }
+
+ if(unit.isInstanceOf[InvokeStmt]) {
+ val invokeStmt = unit.asInstanceOf[InvokeStmt]
+ return analyzeInvokeStmt(invokeStmt.getInvokeExpr)
+ }
+ if(unit.isInstanceOf[soot.jimple.AssignStmt]) {
+ val assignStmt = unit.asInstanceOf[AssignStmt]
+ if(assignStmt.getRightOp.isInstanceOf[InvokeExpr]) {
+ val invokeStmt = assignStmt.getRightOp.asInstanceOf[InvokeExpr]
+ return analyzeInvokeStmt(invokeStmt)
+ }
+ }
+ return SimpleNode
+ }
+
+ def analyzeInvokeStmt(exp: InvokeExpr) : NodeType =
+ exp.getMethod.getName match {
+ case "source" => SourceNode
+ case "sink" => SinkNode
+ case _ => SimpleNode
+ }
+
+}
\ No newline at end of file