/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.plsql.dfa; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.List; import org.junit.Test; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.ast.AbstractNode; import net.sourceforge.pmd.lang.dfa.DataFlowNode; import net.sourceforge.pmd.lang.dfa.NodeType; import net.sourceforge.pmd.lang.dfa.StartOrEndDataFlowNode; import net.sourceforge.pmd.lang.plsql.AbstractPLSQLParserTst; import net.sourceforge.pmd.lang.plsql.PLSQLLanguageModule; import net.sourceforge.pmd.lang.plsql.ast.ASTExpression; import net.sourceforge.pmd.lang.plsql.ast.ASTMethodDeclaration; import net.sourceforge.pmd.lang.plsql.ast.ASTProgramUnit; import net.sourceforge.pmd.lang.plsql.ast.ASTVariableOrConstantDeclarator; import net.sourceforge.pmd.lang.plsql.ast.PLSQLNode; public class StatementAndBraceFinderTest extends AbstractPLSQLParserTst { /** * Java ASTStatementExpression equivalent is inferred as an Expression() * which has an UnlabelledStatement as a parent. */ @Test public void testExpressionParentChildLinks() { ASTExpression ex = getOrderedNodes(ASTExpression.class, TEST1).get(0); DataFlowNode dfn = ex.getDataFlowNode(); assertEquals(3, dfn.getLine()); assertTrue(dfn.getNode() instanceof ASTExpression); List<DataFlowNode> dfns = dfn.getParents(); assertEquals(1, dfns.size()); DataFlowNode parentDfn = dfns.get(0); assertEquals(2, parentDfn.getLine()); assertTrue(parentDfn.getNode() instanceof ASTProgramUnit); ASTProgramUnit exParent = (ASTProgramUnit) parentDfn.getNode(); // Validate the two-way link between Program Unit and Statement assertEquals(ex, exParent.getDataFlowNode().getChildren().get(0).getNode()); assertEquals(exParent, ex.getDataFlowNode().getParents().get(0).getNode()); } @Test public void testVariableOrConstantDeclaratorParentChildLinks() { ASTVariableOrConstantDeclarator vd = getOrderedNodes(ASTVariableOrConstantDeclarator.class, TEST2).get(0); // ASTMethodDeclaration vdParent = (ASTMethodDeclaration) // ((DataFlowNode) vd.getDataFlowNode().getParents().get(0)).getNode(); ASTProgramUnit vdParent = (ASTProgramUnit) vd.getDataFlowNode().getParents().get(0).getNode(); // Validate the two-way link between Program Unit and Variable assertEquals(vd, vdParent.getDataFlowNode().getChildren().get(0).getNode()); assertEquals(vdParent, vd.getDataFlowNode().getParents().get(0).getNode()); } @Test public void testIfStmtHasCorrectTypes() { ASTExpression exp = getOrderedNodes(ASTExpression.class, TEST3).get(0); assertEquals(5, exp.getDataFlowNode().getFlow().size()); DataFlowNode dfn = exp.getDataFlowNode().getFlow().get(2); assertTrue(dfn.isType(NodeType.IF_EXPR)); assertEquals(3, dfn.getLine()); dfn = exp.getDataFlowNode().getFlow().get(3); assertTrue(dfn.isType(NodeType.IF_LAST_STATEMENT_WITHOUT_ELSE)); assertEquals(3, dfn.getLine()); } @Test public void testWhileStmtHasCorrectTypes() { ASTExpression exp = getOrderedNodes(ASTExpression.class, TEST4).get(0); DataFlowNode dfn = exp.getDataFlowNode().getFlow().get(2); assertTrue(dfn.isType(NodeType.WHILE_EXPR)); dfn = exp.getDataFlowNode().getFlow().get(3); assertTrue(dfn.isType(NodeType.WHILE_LAST_STATEMENT)); } @Test public void testForStmtHasCorrectTypes() { ASTExpression exp = getOrderedNodes(ASTExpression.class, TEST5).get(0); DataFlowNode dfn = null; dfn = exp.getDataFlowNode().getFlow().get(0); assertTrue(dfn instanceof StartOrEndDataFlowNode); dfn = exp.getDataFlowNode().getFlow().get(1); assertTrue(dfn.getNode() instanceof ASTProgramUnit); assertEquals(2, dfn.getLine()); dfn = exp.getDataFlowNode().getFlow().get(2); assertEquals(3, dfn.getLine()); assertTrue(dfn.isType(NodeType.FOR_EXPR)); assertTrue(dfn.isType(NodeType.FOR_BEFORE_FIRST_STATEMENT)); dfn = exp.getDataFlowNode().getFlow().get(3); assertEquals(3, dfn.getLine()); assertTrue(dfn.isType(NodeType.FOR_END)); } @Test public void testSimpleCaseStmtHasCorrectTypes() { ASTExpression exp = getOrderedNodes(ASTExpression.class, TEST6).get(0); DataFlowNode dfn = null; dfn = exp.getDataFlowNode().getFlow().get(0); assertTrue(dfn instanceof StartOrEndDataFlowNode); dfn = exp.getDataFlowNode().getFlow().get(1); assertEquals(2, dfn.getLine()); assertTrue(dfn.getNode() instanceof ASTProgramUnit); dfn = exp.getDataFlowNode().getFlow().get(2); assertEquals(4, dfn.getLine()); assertTrue(dfn.isType(NodeType.SWITCH_START)); assertTrue(dfn.isType(NodeType.CASE_LAST_STATEMENT)); dfn = exp.getDataFlowNode().getFlow().get(3); assertEquals(5, dfn.getLine()); assertTrue(dfn.isType(NodeType.CASE_LAST_STATEMENT)); assertTrue(dfn.isType(NodeType.BREAK_STATEMENT)); dfn = exp.getDataFlowNode().getFlow().get(4); assertEquals(6, dfn.getLine()); assertTrue(dfn.isType(NodeType.SWITCH_LAST_DEFAULT_STATEMENT)); assertTrue(dfn.isType(NodeType.BREAK_STATEMENT)); dfn = exp.getDataFlowNode().getFlow().get(5); assertEquals(7, dfn.getLine()); assertTrue(dfn.isType(NodeType.SWITCH_END)); } /* * @Test public void testSearchedCaseStmtHasCorrectTypes() * { List<ASTStatement> statements = getOrderedNodes(ASTStatement.class, * TEST7); List<ASTExpression> expressions = * getOrderedNodes(ASTExpression.class, TEST7); * * ASTStatement st = statements.get(0); ASTStatement st1 = * statements.get(1); ASTStatement st2 = statements.get(2); ASTStatement st3 * = statements.get(3); * System.err.println("testSearchedCaseStmtHasCorrectTypes-st(0)="+st. * getBeginLine()); * * ASTExpression ex = expressions.get(0); ASTExpression ex1 = * expressions.get(1); ASTExpression ex2 = expressions.get(2); ASTExpression * ex3 = expressions.get(3); ASTExpression ex4 = expressions.get(4); * System.err.println("ASTExpression="+ex ); * * DataFlowNode dfn = null; //dfn = ex.getDataFlowNode().getFlow().get(0); * //dfn = st.getDataFlowNode().getFlow().get(0); dfn = (DataFlowNode) * st.getDataFlowNode(); System.err.println("DataFlowNode(st-0)="+dfn ) ; * System.err.println("DataFlowNode(st-1)="+st1.getDataFlowNode() ) ; * System.err.println("DataFlowNode(st-2)="+st2.getDataFlowNode() ) ; * System.err.println("DataFlowNode(st-3)="+st3.getDataFlowNode() ) ; * * System.err.println("DataFlowNode(ex-0)="+ex.getDataFlowNode() ) ; * System.err.println("DataFlowNode(ex-1)="+ex1.getDataFlowNode() ) ; * System.err.println("DataFlowNode(ex-2)="+ex2.getDataFlowNode() ) ; * System.err.println("DataFlowNode(ex-3)="+ex3.getDataFlowNode() ) ; * System.err.println("DataFlowNode(ex-4)="+ex4.getDataFlowNode() ) ; * List<DataFlowNode> dfns = dfn.getFlow(); * System.err.println("DataFlowNodes List size="+dfns.size()) ; DataFlowNode * firstDfn = dfns.get(0); System.err.println("firstDataFlowNode="+firstDfn * ) ; * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(0)="+dfn); * dfn = st.getDataFlowNode().getFlow().get(1); * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(1)="+dfn); * dfn = st.getDataFlowNode().getFlow().get(2); * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(2)="+dfn); * assertTrue(dfn.isType(NodeType.SWITCH_START)); dfn = * st.getDataFlowNode().getFlow().get(3); * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(3)="+dfn); * assertTrue(dfn.isType(NodeType.CASE_LAST_STATEMENT)); //dfn = * st.getDataFlowNode().getFlow().get(4); * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(5)="+dfn); * assertTrue(dfn.isType(NodeType.CASE_LAST_STATEMENT)); dfn = * st.getDataFlowNode().getFlow().get(5); * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(7)="+dfn); * assertTrue(dfn.isType(NodeType.SWITCH_LAST_DEFAULT_STATEMENT)); dfn = * st.getDataFlowNode().getFlow().get(6); * System.err.println("testSearchedCaseStmtHasCorrectTypes-dfn(8)="+dfn); * assertTrue(dfn.isType(NodeType.SWITCH_END)); } */ @Test public void testLabelledStmtHasCorrectTypes() { ASTExpression exp = getOrderedNodes(ASTExpression.class, TEST8).get(0); DataFlowNode dfn = exp.getDataFlowNode().getFlow().get(2); assertEquals(3, dfn.getLine()); assertTrue(dfn.isType(NodeType.LABEL_STATEMENT)); } @Test public void testOnlyWorksForMethodsAndConstructors() { StatementAndBraceFinder sbf = new StatementAndBraceFinder(LanguageRegistry.getLanguage(PLSQLLanguageModule.NAME) .getDefaultVersion().getLanguageVersionHandler().getDataFlowHandler()); PLSQLNode node = new ASTMethodDeclaration(1); ((AbstractNode) node).testingOnlySetBeginColumn(1); sbf.buildDataFlowFor(node); // sbf.buildDataFlowFor(new ASTConstructorDeclaration(1)); node = new ASTProgramUnit(1); ((AbstractNode) node).testingOnlySetBeginColumn(1); sbf.buildDataFlowFor(node); } private static final String TEST1 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS BEGIN" + PMD.EOL + " x := 2;" + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; private static final String TEST2 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS " + PMD.EOL + " int x; " + PMD.EOL + " BEGIN NULL ;" + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; private static final String TEST3 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS BEGIN" + PMD.EOL + " if (x) THEN NULL; END IF; " + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; private static final String TEST4 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS BEGIN" + PMD.EOL + " while (x) LOOP NULL; END LOOP;" + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; private static final String TEST5 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS BEGIN" + PMD.EOL + " for i in 0..9 LOOP NULL; END LOOP;" + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; private static final String TEST6 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS " + PMD.EOL + " BEGIN" + PMD.EOL + " CASE 1 " + PMD.EOL + " WHEN 0 THEN NULL; " + PMD.EOL + " WHEN 1 THEN NULL; " + PMD.EOL + " ELSE NULL;" + PMD.EOL + " END CASE; " + PMD.EOL + " END bar; " + PMD.EOL + "END foo;"; private static final String TEST7 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS " + PMD.EOL + " BEGIN" + PMD.EOL + " CASE " + PMD.EOL + " WHEN 0=1 THEN NULL; " + PMD.EOL + " WHEN 1=1 THEN NULL; " + PMD.EOL + " ELSE NULL;" + PMD.EOL + " END CASE;" + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; private static final String TEST8 = "CREATE OR REPLACE PACKAGE BODY Foo AS" + PMD.EOL + " PROCEDURE bar IS BEGIN" + PMD.EOL + " <<label>> NULL;" + PMD.EOL + " END bar;" + PMD.EOL + "END foo;"; }