389 lines
15 KiB
Java
389 lines
15 KiB
Java
/******************************************************************************
|
|
* 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;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
import junit.framework.Assert;
|
|
|
|
import org.junit.Test;
|
|
|
|
import com.ibm.wala.cast.tree.CAstNode;
|
|
import com.ibm.wala.cast.tree.impl.CAstImpl;
|
|
import com.ibm.wala.cast.util.CAstPattern;
|
|
import com.ibm.wala.cast.util.CAstPrinter;
|
|
import com.ibm.wala.cast.util.CAstPattern.Segments;
|
|
import com.ibm.wala.core.tests.util.WalaTestCase;
|
|
|
|
public class TestCAstPattern extends WalaTestCase {
|
|
|
|
private static final int NAME_ASSERTION_SINGLE = 501;
|
|
|
|
private static final int NAME_ASSERTION_MULTI = 502;
|
|
|
|
private static class TestingCAstImpl extends CAstImpl {
|
|
private final Map testNameMap = new HashMap();
|
|
|
|
@SuppressWarnings("unchecked")
|
|
public CAstNode makeNode(int kind, CAstNode children[]) {
|
|
if (kind == NAME_ASSERTION_SINGLE || kind == NAME_ASSERTION_MULTI) {
|
|
assert children.length == 2;
|
|
assert children[0].getValue() instanceof String;
|
|
@SuppressWarnings("unused")
|
|
CAstNode result = children[1];
|
|
if (kind == NAME_ASSERTION_SINGLE) {
|
|
testNameMap.put(children[0].getValue(), children[1]);
|
|
} else {
|
|
if (!testNameMap.containsKey(children[0].getValue())) {
|
|
testNameMap.put(children[0].getValue(), new ArrayList());
|
|
}
|
|
|
|
((List) testNameMap.get(children[0].getValue())).add(children[1]);
|
|
}
|
|
return children[1];
|
|
} else {
|
|
return super.makeNode(kind, children);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
private void test(CAstPattern p, CAstNode n, Map names) {
|
|
System.err.println(("testing pattern " + p));
|
|
System.err.println(("testing with input " + CAstPrinter.print(n)));
|
|
|
|
if (names == null) {
|
|
Assert.assertFalse(p.match(n, null));
|
|
} else {
|
|
Segments s = CAstPattern.match(p, n);
|
|
Assert.assertTrue(s != null);
|
|
for (Iterator ns = names.keySet().iterator(); ns.hasNext();) {
|
|
String nm = (String) ns.next();
|
|
Object o = names.get(nm);
|
|
if (o instanceof CAstNode) {
|
|
System.err.println(("found " + CAstPrinter.print(s.getSingle(nm)) + " for " + nm));
|
|
Assert.assertTrue("for name " + nm + ": expected " + names.get(nm) + " but got " + s.getSingle(nm), names.get(nm).equals(
|
|
s.getSingle(nm)));
|
|
} else {
|
|
for (Iterator cs = s.getMultiple(nm).iterator(); cs.hasNext();) {
|
|
System.err.println(("found " + CAstPrinter.print((CAstNode) cs.next()) + " for " + nm));
|
|
}
|
|
Assert.assertTrue("for name " + nm + ": expected " + names.get(nm) + " but got " + s.getMultiple(nm), names.get(nm)
|
|
.equals(s.getMultiple(nm)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private final CAstPattern simpleNamePattern = CAstPattern.parse("<top>BINARY_EXPR(\"+\",<left>\"prefix\",\"suffix\")");
|
|
|
|
private final CAstNode simpleNameAst;
|
|
|
|
private final Map simpleNameMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleNameAst = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("left"), Ast.makeConstant("prefix")), Ast
|
|
.makeConstant("suffix")));
|
|
|
|
simpleNameMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleName() {
|
|
test(simpleNamePattern, simpleNameAst, simpleNameMap);
|
|
}
|
|
|
|
private final CAstPattern simpleStarNamePattern = CAstPattern.parse("<top>BINARY_EXPR(\"+\",*,<right>\"suffix\")");
|
|
|
|
private final CAstNode simpleStarNameAst;
|
|
|
|
private final Map simpleStarNameMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleStarNameAst = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeConstant("prefix"), Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("right"), Ast
|
|
.makeConstant("suffix"))));
|
|
|
|
simpleStarNameMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleStarName() {
|
|
test(simpleStarNamePattern, simpleStarNameAst, simpleStarNameMap);
|
|
}
|
|
|
|
private final CAstPattern simpleRepeatedPattern = CAstPattern.parse("<top>BINARY_EXPR(\"+\",<children>@(VAR(*))@)");
|
|
|
|
private final CAstNode simpleRepeatedAstOne;
|
|
|
|
private final Map simpleRepeatedMapOne;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleRepeatedAstOne = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("suffix")))));
|
|
|
|
simpleRepeatedMapOne = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleRepeatedOne() {
|
|
test(simpleRepeatedPattern, simpleRepeatedAstOne, simpleRepeatedMapOne);
|
|
}
|
|
|
|
private final CAstNode simpleRepeatedAstTwo;
|
|
|
|
private final Map simpleRepeatedMapTwo;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleRepeatedAstTwo = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("prefix"))), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("suffix")))));
|
|
|
|
simpleRepeatedMapTwo = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleRepeatedTwo() {
|
|
test(simpleRepeatedPattern, simpleRepeatedAstTwo, simpleRepeatedMapTwo);
|
|
}
|
|
|
|
private final CAstNode simpleRepeatedAstThree;
|
|
|
|
private final Map simpleRepeatedMapThree;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleRepeatedAstThree = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("prefix"))), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("middle"))), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("suffix")))));
|
|
|
|
simpleRepeatedMapThree = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleRepeatedThree() {
|
|
test(simpleRepeatedPattern, simpleRepeatedAstThree, simpleRepeatedMapThree);
|
|
}
|
|
|
|
private final CAstPattern simpleDoubleStarPattern = CAstPattern.parse("<top>BINARY_EXPR(\"+\",<children>**)");
|
|
|
|
private final CAstNode simpleDoubleStarAst;
|
|
|
|
private final Map simpleDoubleStarMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleDoubleStarAst = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("prefix"))), Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("children"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("suffix")))));
|
|
|
|
simpleDoubleStarMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleDoubleStar() {
|
|
test(simpleDoubleStarPattern, simpleDoubleStarAst, simpleDoubleStarMap);
|
|
}
|
|
|
|
private final CAstPattern simpleAlternativePattern = CAstPattern
|
|
.parse("<top>BINARY_EXPR(\"+\",<firstchild>|(VAR(\"suffix\")||VAR(\"prefix\"))|,*)");
|
|
|
|
private final CAstNode simpleAlternativeAst;
|
|
|
|
private final Map simpleAlternativeMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleAlternativeAst = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("firstchild"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("prefix"))), Ast.makeNode(CAstNode.VAR, Ast.makeConstant("suffix"))));
|
|
|
|
simpleAlternativeMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleAlternative() {
|
|
test(simpleAlternativePattern, simpleAlternativeAst, simpleAlternativeMap);
|
|
}
|
|
|
|
private final CAstPattern simpleOptionalPattern = CAstPattern
|
|
.parse("<top>BINARY_EXPR(\"+\",?(VAR(\"prefix\"))?,<child>VAR(\"suffix\"))");
|
|
|
|
private final CAstNode simpleOptionalAstWith;
|
|
|
|
private final Map simpleOptionalMapWith;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleOptionalAstWith = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeConstant("prefix")), Ast.makeNode(NAME_ASSERTION_SINGLE, Ast
|
|
.makeConstant("child"), Ast.makeNode(CAstNode.VAR, Ast.makeConstant("suffix")))));
|
|
|
|
simpleOptionalMapWith = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleOptionalWith() {
|
|
test(simpleOptionalPattern, simpleOptionalAstWith, simpleOptionalMapWith);
|
|
}
|
|
|
|
private final CAstNode simpleOptionalAstNot;
|
|
|
|
private final Map simpleOptionalMapNot;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
simpleOptionalAstNot = Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("top"), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(NAME_ASSERTION_SINGLE, Ast.makeConstant("child"), Ast.makeNode(CAstNode.VAR, Ast
|
|
.makeConstant("suffix")))));
|
|
|
|
simpleOptionalMapNot = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testSimpleOptionalNot() {
|
|
test(simpleOptionalPattern, simpleOptionalAstNot, simpleOptionalMapNot);
|
|
}
|
|
|
|
private final String recursiveTreeStr = "|({leaf}|(<const>CONSTANT()||VAR(<vars>*))|||{node}BINARY_EXPR(\"+\",`leaf`,|(`leaf`||`node`)|))|";
|
|
|
|
private final CAstPattern recursiveTreePattern = CAstPattern.parse(recursiveTreeStr);
|
|
|
|
private final CAstNode recursiveTreeOneAst;
|
|
|
|
private final Map recursiveTreeOneMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
recursiveTreeOneAst = Ast.makeNode(CAstNode.BINARY_EXPR, Ast.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("x"))), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("y"))));
|
|
|
|
recursiveTreeOneMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testRecursiveTreeOne() {
|
|
test(recursiveTreePattern, recursiveTreeOneAst, recursiveTreeOneMap);
|
|
}
|
|
|
|
private final CAstNode recursiveTreeTwoAst;
|
|
|
|
private final Map recursiveTreeTwoMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
recursiveTreeTwoAst = Ast.makeNode(CAstNode.BINARY_EXPR, Ast.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("x"))), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast
|
|
.makeConstant("y"))), Ast.makeNode(CAstNode.VAR, Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast
|
|
.makeConstant("z")))));
|
|
|
|
recursiveTreeTwoMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testRecursiveTreeTwo() {
|
|
test(recursiveTreePattern, recursiveTreeTwoAst, recursiveTreeTwoMap);
|
|
}
|
|
|
|
private final CAstNode recursiveTreeFiveAst;
|
|
|
|
private final Map recursiveTreeFiveMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
recursiveTreeFiveAst = Ast.makeNode(CAstNode.BINARY_EXPR, Ast.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("u"))), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast
|
|
.makeConstant("v"))), Ast.makeNode(CAstNode.BINARY_EXPR, Ast.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("w"))), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast
|
|
.makeConstant("x"))), Ast.makeNode(CAstNode.BINARY_EXPR, Ast.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("y"))), Ast.makeNode(CAstNode.VAR, Ast.makeNode(
|
|
NAME_ASSERTION_MULTI, Ast.makeConstant("vars"), Ast.makeConstant("z"))))))));
|
|
|
|
recursiveTreeFiveMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testRecursiveTreeFive() {
|
|
test(recursiveTreePattern, recursiveTreeFiveAst, recursiveTreeFiveMap);
|
|
}
|
|
|
|
private final CAstPattern buggyRecursiveTreePattern = CAstPattern
|
|
.parse("|({leaf}|(<const>CONSTANT()||VAR(<vars>*))|||{node}BINARY_EXPR(\"+\",`leaf`,`node`))|");
|
|
|
|
@Test public void testBuggyRecursiveTreeOne() {
|
|
test(buggyRecursiveTreePattern, recursiveTreeOneAst, null);
|
|
}
|
|
|
|
@Test public void testBuggyRecursiveTreeTwo() {
|
|
test(buggyRecursiveTreePattern, recursiveTreeTwoAst, null);
|
|
}
|
|
|
|
@Test public void testBuggyRecursiveTreeFive() {
|
|
test(buggyRecursiveTreePattern, recursiveTreeFiveAst, null);
|
|
}
|
|
|
|
private static final String extraTestsStr = "BINARY_EXPR(|(\"==\"||\"\\==\")|,|(CONSTANT()||VAR(CONSTANT()))|,|(CONSTANT()||VAR(CONSTANT()))|)";
|
|
|
|
private final CAstPattern testedTreePattern = CAstPattern.parse("{top}|(" + recursiveTreeStr + "||BINARY_EXPR(\",\","
|
|
+ extraTestsStr + ",`top`))|");
|
|
|
|
@Test public void testTestedTreeOne() {
|
|
test(testedTreePattern, recursiveTreeOneAst, recursiveTreeOneMap);
|
|
}
|
|
|
|
@Test public void testTestedTreeTwo() {
|
|
test(testedTreePattern, recursiveTreeTwoAst, recursiveTreeTwoMap);
|
|
}
|
|
|
|
@Test public void testTestedTreeFive() {
|
|
test(testedTreePattern, recursiveTreeFiveAst, recursiveTreeFiveMap);
|
|
}
|
|
|
|
private final CAstNode testedTreeOneAst;
|
|
|
|
private final Map testedTreeOneMap;
|
|
|
|
{
|
|
TestingCAstImpl Ast = new TestingCAstImpl();
|
|
|
|
testedTreeOneAst = Ast.makeNode(CAstNode.BINARY_EXPR, Ast.makeConstant(","), Ast.makeNode(CAstNode.BINARY_EXPR, Ast
|
|
.makeConstant("=="), Ast.makeNode(CAstNode.VAR, Ast.makeConstant("x")), Ast.makeConstant(7)), Ast.makeNode(
|
|
CAstNode.BINARY_EXPR, Ast.makeConstant("+"), Ast.makeNode(CAstNode.VAR, Ast.makeNode(NAME_ASSERTION_MULTI, Ast
|
|
.makeConstant("vars"), Ast.makeConstant("x"))), Ast.makeNode(CAstNode.VAR, Ast.makeNode(NAME_ASSERTION_MULTI, Ast
|
|
.makeConstant("vars"), Ast.makeConstant("y")))));
|
|
|
|
testedTreeOneMap = Ast.testNameMap;
|
|
}
|
|
|
|
@Test public void testTestedTreeOneWithTest() {
|
|
test(testedTreePattern, testedTreeOneAst, testedTreeOneMap);
|
|
}
|
|
|
|
}
|