2007-06-03 21:54:49 +00:00
|
|
|
/******************************************************************************
|
|
|
|
* Copyright (c) 2002 - 2006 IBM Corporation.
|
|
|
|
* All rights reserved. This program and the accompanying materials
|
|
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
|
|
* which accompanies this distribution, and is available at
|
|
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
|
|
*
|
|
|
|
* Contributors:
|
|
|
|
* IBM Corporation - initial API and implementation
|
|
|
|
*****************************************************************************/
|
|
|
|
package com.ibm.wala.cast.test;
|
|
|
|
|
2007-07-05 03:04:43 +00:00
|
|
|
import java.util.Collection;
|
|
|
|
import java.util.Iterator;
|
2007-06-03 21:54:49 +00:00
|
|
|
|
2007-07-05 03:04:43 +00:00
|
|
|
import junit.framework.Assert;
|
2007-06-03 21:54:49 +00:00
|
|
|
|
2011-04-04 15:29:53 +00:00
|
|
|
import com.ibm.wala.cast.loader.AstMethod;
|
|
|
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
2007-07-05 03:04:43 +00:00
|
|
|
import com.ibm.wala.classLoader.CallSiteReference;
|
2007-06-03 21:54:49 +00:00
|
|
|
import com.ibm.wala.core.tests.util.WalaTestCase;
|
2007-07-05 03:04:43 +00:00
|
|
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
|
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
|
|
|
import com.ibm.wala.ssa.IR;
|
2011-04-04 15:29:53 +00:00
|
|
|
import com.ibm.wala.ssa.SSAInstruction;
|
2007-07-05 03:04:43 +00:00
|
|
|
import com.ibm.wala.util.collections.NonNullSingletonIterator;
|
2007-06-03 21:54:49 +00:00
|
|
|
|
|
|
|
public abstract class TestCallGraphShape extends WalaTestCase {
|
|
|
|
|
2011-04-04 15:29:53 +00:00
|
|
|
protected void verifySourceAssertions(CallGraph CG, Object[][] assertionData) {
|
|
|
|
for(Object[] dat : assertionData) {
|
|
|
|
String function = (String) dat[0];
|
|
|
|
for(CGNode N : getNodes(CG, function)) {
|
|
|
|
if (N.getMethod() instanceof AstMethod) {
|
|
|
|
AstMethod M = (AstMethod) N.getMethod();
|
|
|
|
SSAInstruction[] insts = N.getIR().getInstructions();
|
|
|
|
insts: for(int i = 0; i < insts.length; i++) {
|
|
|
|
SSAInstruction inst = insts[i];
|
|
|
|
if (inst != null) {
|
|
|
|
Position pos = M.getSourcePosition(i);
|
|
|
|
if (pos != null) {
|
|
|
|
String fileName = pos.getURL().toString();
|
|
|
|
if (fileName.lastIndexOf('/') >= 0) {
|
|
|
|
fileName = fileName.substring(fileName.lastIndexOf('/')+1);
|
|
|
|
}
|
|
|
|
for(int j = 0; j < assertionData.length; j++) {
|
|
|
|
String file = (String) assertionData[j][1];
|
|
|
|
if (file.indexOf('/') >= 0) {
|
|
|
|
file = file.substring(file.lastIndexOf('/') + 1);
|
|
|
|
}
|
|
|
|
if (file.equalsIgnoreCase(fileName)) {
|
|
|
|
if (pos.getFirstLine() >= (Integer) assertionData[j][2]
|
|
|
|
&&
|
2012-05-08 17:17:01 +00:00
|
|
|
(pos.getLastLine() != -1? pos.getLastLine(): pos.getFirstLine()) <= (Integer) assertionData[j][3]) {
|
2011-04-04 15:29:53 +00:00
|
|
|
System.err.println("found " + inst + " of " + M + " at expected position " + pos);
|
|
|
|
continue insts;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-08 17:17:01 +00:00
|
|
|
Assert.assertTrue("unexpected location " + pos + " for " + inst + " of " + M + "\n" + N.getIR(), false);
|
2011-04-04 15:29:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-03 21:54:49 +00:00
|
|
|
protected static class Name {
|
|
|
|
String name;
|
|
|
|
|
|
|
|
int instructionIndex;
|
|
|
|
|
|
|
|
int vn;
|
|
|
|
|
2007-06-03 23:35:43 +00:00
|
|
|
public Name(int vn, int instructionIndex, String name) {
|
2007-06-03 21:54:49 +00:00
|
|
|
this.vn = vn;
|
|
|
|
this.name = name;
|
|
|
|
this.instructionIndex = instructionIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void verifyNameAssertions(CallGraph CG, Object[][] assertionData) {
|
|
|
|
for (int i = 0; i < assertionData.length; i++) {
|
|
|
|
Iterator NS = getNodes(CG, (String) assertionData[i][0]).iterator();
|
|
|
|
while (NS.hasNext()) {
|
|
|
|
CGNode N = (CGNode) NS.next();
|
2007-07-06 22:08:39 +00:00
|
|
|
IR ir = N.getIR();
|
2007-06-03 21:54:49 +00:00
|
|
|
Name[] names = (Name[]) assertionData[i][1];
|
|
|
|
for (int j = 0; j < names.length; j++) {
|
|
|
|
|
2009-06-03 18:27:39 +00:00
|
|
|
System.err.println("looking for " + names[j].name + ", " + names[j].vn + " in " + N);
|
2007-06-03 21:54:49 +00:00
|
|
|
|
|
|
|
String[] localNames = ir.getLocalNames(names[j].instructionIndex, names[j].vn);
|
|
|
|
|
|
|
|
boolean found = false;
|
|
|
|
for (int k = 0; k < localNames.length; k++) {
|
|
|
|
if (localNames[k].equals(names[j].name)) {
|
|
|
|
found = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-21 13:47:01 +00:00
|
|
|
Assert.assertTrue("no name " + names[j].name + " for " + N + "\n" + ir, found);
|
2007-06-03 21:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void verifyGraphAssertions(CallGraph CG, Object[][] assertionData) {
|
2009-06-03 18:27:39 +00:00
|
|
|
// System.err.println(CG);
|
2007-06-03 21:54:49 +00:00
|
|
|
|
2009-01-19 15:12:39 +00:00
|
|
|
if (assertionData == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-06-03 21:54:49 +00:00
|
|
|
for (int i = 0; i < assertionData.length; i++) {
|
|
|
|
|
|
|
|
check_target: for (int j = 0; j < ((String[]) assertionData[i][1]).length; j++) {
|
2007-07-11 16:24:39 +00:00
|
|
|
Iterator srcs = (assertionData[i][0] instanceof String) ? getNodes(CG, (String) assertionData[i][0]).iterator()
|
|
|
|
: new NonNullSingletonIterator<CGNode>(CG.getFakeRootNode());
|
2007-06-03 21:54:49 +00:00
|
|
|
|
|
|
|
Assert.assertTrue("cannot find " + assertionData[i][0], srcs.hasNext());
|
|
|
|
|
2011-04-27 13:58:56 +00:00
|
|
|
boolean checkAbsence = false;
|
|
|
|
String targetName = ((String[]) assertionData[i][1])[j];
|
|
|
|
if (targetName.startsWith("!")) {
|
|
|
|
checkAbsence = true;
|
|
|
|
targetName = targetName.substring(1);
|
|
|
|
}
|
|
|
|
|
2012-02-21 13:47:01 +00:00
|
|
|
while (srcs.hasNext()) {
|
2007-06-03 21:54:49 +00:00
|
|
|
CGNode src = (CGNode) srcs.next();
|
2007-11-20 15:50:10 +00:00
|
|
|
for (Iterator sites = src.iterateCallSites(); sites.hasNext();) {
|
2007-06-03 21:54:49 +00:00
|
|
|
CallSiteReference sr = (CallSiteReference) sites.next();
|
2011-04-27 13:58:56 +00:00
|
|
|
|
|
|
|
Iterator dsts = getNodes(CG, targetName).iterator();
|
2012-02-23 18:15:05 +00:00
|
|
|
if (! checkAbsence) {
|
|
|
|
Assert.assertTrue("cannot find " + targetName, dsts.hasNext());
|
|
|
|
}
|
|
|
|
|
2007-06-03 21:54:49 +00:00
|
|
|
while (dsts.hasNext()) {
|
|
|
|
CGNode dst = (CGNode) dsts.next();
|
2007-07-11 16:24:39 +00:00
|
|
|
for (Iterator tos = CG.getPossibleTargets(src, sr).iterator(); tos.hasNext();) {
|
2007-06-03 21:54:49 +00:00
|
|
|
if (tos.next().equals(dst)) {
|
2011-04-27 13:58:56 +00:00
|
|
|
if (checkAbsence) {
|
|
|
|
System.err.println(("found unexpected " + src + " --> " + dst + " at " + sr));
|
|
|
|
Assert.assertTrue("found edge " + assertionData[i][0] + " ---> " + targetName, false);
|
|
|
|
} else {
|
|
|
|
System.err.println(("found expected " + src + " --> " + dst + " at " + sr));
|
|
|
|
continue check_target;
|
|
|
|
}
|
2007-06-03 21:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-27 13:58:56 +00:00
|
|
|
System.err.println("cannot find edge " + assertionData[i][0] + " ---> " + targetName);
|
|
|
|
Assert.assertTrue("cannot find edge " + assertionData[i][0] + " ---> " + targetName, checkAbsence);
|
2007-06-03 21:54:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-02 19:30:03 +00:00
|
|
|
|
|
|
|
/**
|
2011-04-04 15:29:53 +00:00
|
|
|
* Verifies that none of the nodes that match the source description has an edge to any of the nodes that match the destination
|
2010-10-02 19:30:03 +00:00
|
|
|
* description. (Used for checking for false connections in the callgraph)
|
|
|
|
*
|
|
|
|
* @param CG
|
|
|
|
* @param sourceDescription
|
|
|
|
* @param destDescription
|
|
|
|
*/
|
|
|
|
protected void verifyNoEdges(CallGraph CG, String sourceDescription, String destDescription) {
|
|
|
|
Collection sources = getNodes(CG, sourceDescription);
|
|
|
|
Collection dests = getNodes(CG, destDescription);
|
|
|
|
for (Object source : sources) {
|
|
|
|
for (Object dest : dests) {
|
|
|
|
for (Iterator<CGNode> i = CG.getSuccNodes((CGNode) source); i.hasNext();) {
|
|
|
|
if (i.next().equals(dest)) {
|
|
|
|
Assert.fail("Found a link from " + source + " to " + dest);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-04 15:29:53 +00:00
|
|
|
protected static final Object ROOT = new Object() {
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "CallGraphRoot";
|
|
|
|
}
|
|
|
|
};
|
2007-06-03 21:54:49 +00:00
|
|
|
|
2011-04-04 15:29:53 +00:00
|
|
|
protected abstract Collection<CGNode> getNodes(CallGraph CG, String functionIdentifier);
|
2007-06-03 21:54:49 +00:00
|
|
|
|
|
|
|
}
|