-
Notifications
You must be signed in to change notification settings - Fork 177
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add test cases for customized entry points
- Loading branch information
1 parent
cb49dd9
commit c45e1c4
Showing
3 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
101 changes: 101 additions & 0 deletions
101
src/test/java/pascal/taie/analysis/pta/CustomEntryPointPlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* | ||
* Tai-e: A Static Analysis Framework for Java | ||
* | ||
* Copyright (C) 2022 Tian Tan <tiantan@nju.edu.cn> | ||
* Copyright (C) 2022 Yue Li <yueli@nju.edu.cn> | ||
* | ||
* This file is part of Tai-e. | ||
* | ||
* Tai-e is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License | ||
* as published by the Free Software Foundation, either version 3 | ||
* of the License, or (at your option) any later version. | ||
* | ||
* Tai-e is distributed in the hope that it will be useful,but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General | ||
* Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with Tai-e. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package pascal.taie.analysis.pta; | ||
|
||
import pascal.taie.analysis.pta.core.heap.Descriptor; | ||
import pascal.taie.analysis.pta.core.heap.HeapModel; | ||
import pascal.taie.analysis.pta.core.heap.Obj; | ||
import pascal.taie.analysis.pta.core.solver.DeclaredParamProvider; | ||
import pascal.taie.analysis.pta.core.solver.EmptyParamProvider; | ||
import pascal.taie.analysis.pta.core.solver.EntryPoint; | ||
import pascal.taie.analysis.pta.core.solver.Solver; | ||
import pascal.taie.analysis.pta.core.solver.SpecifiedParamProvider; | ||
import pascal.taie.analysis.pta.plugin.Plugin; | ||
import pascal.taie.language.classes.ClassHierarchy; | ||
import pascal.taie.language.classes.ClassNames; | ||
import pascal.taie.language.classes.JClass; | ||
import pascal.taie.language.classes.JField; | ||
import pascal.taie.language.classes.JMethod; | ||
import pascal.taie.language.type.TypeSystem; | ||
|
||
public class CustomEntryPointPlugin implements Plugin { | ||
|
||
private Solver solver; | ||
|
||
private ClassHierarchy hierarchy; | ||
|
||
private TypeSystem typeSystem; | ||
|
||
private HeapModel heapModel; | ||
|
||
@Override | ||
public void setSolver(Solver solver) { | ||
this.solver = solver; | ||
this.hierarchy = solver.getHierarchy(); | ||
this.typeSystem = solver.getTypeSystem(); | ||
this.heapModel = solver.getHeapModel(); | ||
} | ||
|
||
@Override | ||
public void onStart() { | ||
JClass clz = hierarchy.getClass("CustomEntryPoints"); | ||
assert clz != null; | ||
|
||
JMethod emptyParam = clz.getDeclaredMethod("entryWithEmptyParam"); | ||
assert emptyParam != null; | ||
solver.addEntryPoint(new EntryPoint(emptyParam, EmptyParamProvider.get())); | ||
|
||
JMethod declaredParam1 = clz.getDeclaredMethod("entryWithDeclaredParam1"); | ||
assert declaredParam1 != null; | ||
solver.addEntryPoint(new EntryPoint( | ||
declaredParam1, new DeclaredParamProvider(declaredParam1, heapModel, 1))); | ||
|
||
JMethod declaredParam2 = clz.getDeclaredMethod("entryWithDeclaredParam2"); | ||
assert declaredParam2 != null; | ||
solver.addEntryPoint(new EntryPoint( | ||
declaredParam2, new DeclaredParamProvider(declaredParam2, heapModel, 2))); | ||
|
||
JMethod specifiedParam = clz.getDeclaredMethod("entryWithSpecifiedParam"); | ||
assert specifiedParam != null; | ||
SpecifiedParamProvider.Builder paramProviderBuilder = | ||
new SpecifiedParamProvider.Builder(specifiedParam); | ||
Obj thisObj = heapModel.getMockObj(Descriptor.ENTRY_DESC, "MethodParam{this}", | ||
clz.getType(), specifiedParam); | ||
Obj p0 = heapModel.getMockObj(Descriptor.ENTRY_DESC, "MethodParam{0}", | ||
specifiedParam.getParamType(0), specifiedParam); | ||
Obj p1 = heapModel.getMockObj(Descriptor.ENTRY_DESC, "MethodParam{1}", | ||
specifiedParam.getParamType(1), specifiedParam); | ||
Obj stringObj = heapModel.getMockObj(Descriptor.ENTRY_DESC, "MethodParam{0}.s1", | ||
typeSystem.getType(ClassNames.STRING), specifiedParam); | ||
Obj param1Obj = heapModel.getMockObj(Descriptor.ENTRY_DESC, "MethodParam{1}[*]", | ||
typeSystem.getType("Param1"), specifiedParam); | ||
JField s1Field = hierarchy.getField("<Param1: java.lang.String s1>"); | ||
paramProviderBuilder.addThisObj(thisObj) | ||
.addParamObj(0, p0) | ||
.addFieldObj(p0, s1Field, stringObj) | ||
.addParamObj(1, p1) | ||
.addArrayObj(p1, param1Obj) | ||
.setDelegate(new DeclaredParamProvider(specifiedParam, heapModel)); | ||
solver.addEntryPoint(new EntryPoint(specifiedParam, paramProviderBuilder.build())); | ||
} | ||
} |
121 changes: 121 additions & 0 deletions
121
src/test/java/pascal/taie/analysis/pta/CustomEntryPointTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
/* | ||
* Tai-e: A Static Analysis Framework for Java | ||
* | ||
* Copyright (C) 2022 Tian Tan <tiantan@nju.edu.cn> | ||
* Copyright (C) 2022 Yue Li <yueli@nju.edu.cn> | ||
* | ||
* This file is part of Tai-e. | ||
* | ||
* Tai-e is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License | ||
* as published by the Free Software Foundation, either version 3 | ||
* of the License, or (at your option) any later version. | ||
* | ||
* Tai-e is distributed in the hope that it will be useful,but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General | ||
* Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with Tai-e. If not, see <https://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
package pascal.taie.analysis.pta; | ||
|
||
import org.junit.jupiter.api.Test; | ||
import pascal.taie.Main; | ||
import pascal.taie.World; | ||
import pascal.taie.analysis.graph.callgraph.CallGraph; | ||
import pascal.taie.analysis.graph.callgraph.CallGraphBuilder; | ||
import pascal.taie.analysis.graph.callgraph.Edge; | ||
import pascal.taie.ir.stmt.Invoke; | ||
import pascal.taie.language.classes.ClassHierarchy; | ||
import pascal.taie.language.classes.JMethod; | ||
import pascal.taie.util.collection.MultiMap; | ||
import pascal.taie.util.collection.MultiMapCollector; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
|
||
public class CustomEntryPointTest { | ||
|
||
private static final String[][] CALLER_CALLEE_RELATIONS = { | ||
{ | ||
"false", | ||
"<CustomEntryPoints: void entryWithEmptyParam(Param1,Param1[])>", | ||
"<Param1: java.lang.String getS1()>", | ||
}, | ||
{ | ||
"false", | ||
"<CustomEntryPoints: void entryWithEmptyParam(Param1,Param1[])>", | ||
"<Param1: void setS2(java.lang.String)>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithDeclaredParam1(Param1,Param1[])>", | ||
"<Param1: java.lang.String getS1()>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithDeclaredParam1(Param1,Param1[])>", | ||
"<Param1: void setS2(java.lang.String)>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithDeclaredParam2(Param2)>", | ||
"<Param2: java.lang.String getS1()>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithDeclaredParam2(Param2)>", | ||
"<Param2: Param1 getP1()>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithDeclaredParam2(Param2)>", | ||
"<Param1: java.lang.String getS2()>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithSpecifiedParam(Param1,Param1[],java.lang.String)>", | ||
"<Param1: java.lang.String getS1()>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithSpecifiedParam(Param1,Param1[],java.lang.String)>", | ||
"<Param1: void setS2(java.lang.String)>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithSpecifiedParam(Param1,Param1[],java.lang.String)>", | ||
"<java.lang.String: java.lang.String toString()>", | ||
}, | ||
{ | ||
"true", | ||
"<CustomEntryPoints: void entryWithSpecifiedParam(Param1,Param1[],java.lang.String)>", | ||
"<java.lang.Object: java.lang.String toString()>", | ||
}, | ||
}; | ||
|
||
@Test | ||
void test() { | ||
Main.main("-pp", | ||
"-cp", "src/test/resources/pta/entrypoint", | ||
"--input-classes", "CustomEntryPoints", | ||
"-a", "pta=only-app:true;implicit-entries:false;" | ||
+ "plugins:[pascal.taie.analysis.pta.CustomEntryPointPlugin];", | ||
"-a", "cg"); | ||
CallGraph<Invoke, JMethod> cg = World.get().getResult(CallGraphBuilder.ID); | ||
MultiMap<JMethod, JMethod> callerCalleeRelations = cg.edges().collect( | ||
MultiMapCollector.get(e -> e.getCallSite().getContainer(), Edge::getCallee)); | ||
ClassHierarchy hierarchy = World.get().getClassHierarchy(); | ||
for (String[] callerCalleeRelation : CALLER_CALLEE_RELATIONS) { | ||
boolean reachable = Boolean.parseBoolean(callerCalleeRelation[0]); | ||
JMethod caller = hierarchy.getMethod(callerCalleeRelation[1]); | ||
JMethod callee = hierarchy.getMethod(callerCalleeRelation[2]); | ||
assertEquals(reachable, callerCalleeRelations.contains(caller, callee), | ||
caller + " -> " + callee); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
public class CustomEntryPoints { | ||
|
||
// static entrypoint with empty parameters | ||
public static void entryWithEmptyParam(Param1 p1, Param1[] p1s) { | ||
String s1 = p1.getS1(); // Param1.getS1 is not reachable | ||
p1s[0].setS2(s1); // Param1.setS2 is not reachable | ||
} | ||
|
||
// static entrypoint with declared parameters | ||
public static void entryWithDeclaredParam1(Param1 p1, Param1[] p1s) { | ||
String s1 = p1.getS1(); // Param1.getS1 is reachable | ||
p1s[0].setS2(s1); // Param1.setS2 is reachable | ||
} | ||
|
||
// static entrypoint with declared parameters | ||
public static void entryWithDeclaredParam2(Param2 p2) { | ||
String s1 = p2.getS1(); // Param2.getS1 is reachable | ||
Param1 p1 = p2.getP1(); // p1 is not null if k >= 1 | ||
String s2 = p1.getS2(); // Param1.getS2 is reachable if k >= 2 | ||
} | ||
|
||
// instance entrypoint with specified parameters | ||
public void entryWithSpecifiedParam(Param1 p1, Param1[] p1s, String s) { | ||
String s1 = p1.getS1(); // Param1.getS1 is reachable | ||
p1s[0].setS2(s1); // Param1.setS2 is reachable | ||
s.toString(); // String.toString is reachable | ||
this.toString(); // Object.toString is reachable | ||
} | ||
|
||
} | ||
|
||
class Param1 { | ||
|
||
private String s1; | ||
|
||
private String s2; | ||
|
||
public Param1(String s1, String s2) { | ||
this.s1 = s1; | ||
this.s2 = s2; | ||
} | ||
|
||
public String getS1() { | ||
return s1; | ||
} | ||
|
||
public String getS2() { | ||
return s2; | ||
} | ||
|
||
public void setS1(String s1) { | ||
this.s1 = s1; | ||
} | ||
|
||
public void setS2(String s2) { | ||
this.s2 = s2; | ||
} | ||
|
||
} | ||
|
||
class Param2 { | ||
|
||
private final String s1; | ||
|
||
private final Param1 p1; | ||
|
||
public Param2(String s1, Param1 p1) { | ||
this.s1 = s1; | ||
this.p1 = p1; | ||
} | ||
|
||
public String getS1() { | ||
return s1; | ||
} | ||
|
||
public Param1 getP1() { | ||
return p1; | ||
} | ||
|
||
} |