Skip to content

Commit

Permalink
Adds a very basic test case of the LambdaMetaFactory with a CHA call …
Browse files Browse the repository at this point in the history
…graph.

Test case is copied from the 'Java Call Graph Test Suite (JCG)' project (https://bitbucket.org/delors/jcg/src/master/)
  • Loading branch information
mbenz89 committed Dec 20, 2018
1 parent 625489b commit 0876912
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/main/generated/singletons/soot/Singletons.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/* THIS FILE IS AUTOMATICALLY GENERATED FROM soot/singletons.xml DO NOT EDIT! */

/** A class to group together all the global variables in Soot. */
@javax.annotation.Generated(value = "Saxonica v3.0", date = "2018-08-13T11:22:21.975+02:00", comments = "from singletons.xml")
@javax.annotation.Generated(value = "Saxonica v3.0", date = "2018-10-31T13:12:15.434+01:00", comments = "from singletons.xml")
public class Singletons {

public final class Global {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package soot.lambdaMetaFactory;

import com.google.common.collect.Lists;

import java.util.List;

import org.junit.Assert;
import org.junit.Test;

import soot.PhaseOptions;
import soot.Scene;
import soot.SootMethod;
import soot.jimple.toolkits.callgraph.CallGraph;
import soot.jimple.toolkits.callgraph.Edge;
import soot.testing.framework.AbstractTestingFramework;

/**
* @author Manuel Benz created on 31.10.18
*/
public class LambdaMetaFactoryCHATest extends AbstractTestingFramework {

private static final String TEST_METHOD_SUBSIG = "void main()";

@Test
public void lambda1() {
String testClass = "soot.lambdaMetaFactory.jcg.Lambda1";

final SootMethod target
= prepareTarget(methodSigFromComponents(testClass, TEST_METHOD_SUBSIG), testClass, "java.util.function.Function");

final CallGraph cg = Scene.v().getCallGraph();

final SootMethod bootstrap
= Scene.v().getMethod("<soot.dummy.lambda$main$0$1: java.util.function.Function bootstrap$()>");
final SootMethod metaFactoryConstructor = Scene.v().getMethod("<soot.dummy.lambda$main$0$1: void <init>()>");
final SootMethod genericApply
= Scene.v().getMethod("<soot.dummy.lambda$main$0$1: java.lang.Object apply(java.lang.Object)>");
final SootMethod concreteApply
= Scene.v().getMethod("<soot.dummy.lambda$main$0$1: java.lang.Boolean apply(java.lang.Integer)>");
final SootMethod lambdaBody
= Scene.v().getMethod(methodSigFromComponents(testClass, "java.lang.Boolean lambda$main$0(java.lang.Integer)"));
final SootMethod doSomething = Scene.v().getMethod("<soot.lambdaMetaFactory.jcg.Lambda1: void doSomething()>");

final List<Edge> edgesFromTarget = Lists.newArrayList(cg.edgesOutOf(target));

Assert.assertTrue("There should be an edge from main to the bootstrap method of the synthetic LambdaMetaFactory",
edgesFromTarget.stream().anyMatch(e -> e.tgt().equals(bootstrap) && e.isStatic()));
Assert.assertTrue("There should be an edge to the constructor of the LambdaMetaFactory in the bootstrap method",
Lists.newArrayList(cg.edgesOutOf(bootstrap)).stream()
.anyMatch(e -> e.tgt().equals(metaFactoryConstructor) && e.isSpecial()));
Assert.assertTrue(
"There should be an interface invocation on the synthetic LambdaMetaFactory's implementation of the functional interface (bridge) in the main method",
edgesFromTarget.stream().anyMatch(e -> e.getTgt().equals(genericApply) && e.isInstance()));
Assert.assertTrue(
"There should be a virtual invocation of the synthetic LambdaMetaFactory's implementation of the functional interface in the bridge method",
Lists.newArrayList(cg.edgesOutOf(genericApply)).stream()
.anyMatch(e -> e.tgt().equals(concreteApply) && e.isVirtual()));

Assert.assertTrue(
"There should be a static call to the lambda body implementation in the generated functional interface implementation of the synthetic LambdaMetaFactory",
Lists.newArrayList(cg.edgesOutOf(concreteApply)).stream()
.anyMatch(e -> e.getTgt().equals(lambdaBody) && e.isStatic()));

Assert.assertTrue("There should be a static call to the doSomething method in actual lambda body implementation", Lists
.newArrayList(cg.edgesOutOf(lambdaBody)).stream().anyMatch(e -> e.getTgt().equals(doSomething) && e.isStatic()));
}

@Override
protected void setupSoot() {
PhaseOptions.v().setPhaseOption("cg.cha", "on");
}
}
17 changes: 17 additions & 0 deletions src/systemTest/targets/soot/lambdaMetaFactory/jcg/Lambda1.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package soot.lambdaMetaFactory.jcg;

import java.util.function.Function;

class Lambda1 {
private static void doSomething() {
// call in lambda
}

public void main() {
Function<Integer, Boolean> isEven = (Integer a) -> {
doSomething();
return a % 2 == 0;
};
isEven.apply(2);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* The code contained in this package is copied from 'The Java Call Graph Test Suite (JCG)' project:
* https://bitbucket.org/delors/jcg/src/master/
*
*
* @author Manuel Benz created on 31.10.18
*/
package soot.lambdaMetaFactory.jcg;

0 comments on commit 0876912

Please sign in to comment.