/** * BSD-style license; for more info see http://pmd.sourceforge.net/license.html */ package net.sourceforge.pmd.lang.java.rule; import static org.junit.Assert.assertEquals; import java.io.StringReader; import java.util.HashMap; import java.util.List; import org.junit.Before; import org.junit.Test; import net.sourceforge.pmd.PMD; import net.sourceforge.pmd.PropertyDescriptor; import net.sourceforge.pmd.Report; import net.sourceforge.pmd.RuleContext; import net.sourceforge.pmd.RuleSet; import net.sourceforge.pmd.RuleSetFactory; import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.lang.Parser; import net.sourceforge.pmd.lang.ParserOptions; import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.java.JavaLanguageModule; import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit; import net.sourceforge.pmd.lang.rule.XPathRule; import net.sourceforge.pmd.lang.rule.properties.StringProperty; import net.sourceforge.pmd.lang.rule.xpath.JaxenXPathRuleQuery; import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery; import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery; import net.sourceforge.pmd.testframework.RuleTst; /** * @author daniels */ public class XPathRuleTest extends RuleTst { XPathRule rule; @Before public void setUp() { rule = new XPathRule(); rule.setLanguage(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)); rule.setMessage("XPath Rule Failed"); } @Test public void testPluginname() throws Exception { rule.setXPath("//VariableDeclaratorId[string-length(@Image) < 3]"); rule.setMessage("{0}"); PMD p = new PMD(); RuleContext ctx = new RuleContext(); Report report = new Report(); ctx.setReport(report); ctx.setSourceCodeFilename("n/a"); RuleSet rules = new RuleSetFactory().createSingleRuleRuleSet(rule); p.getSourceCodeProcessor().processSourceCode(new StringReader(TEST1), new RuleSets(rules), ctx); RuleViolation rv = report.iterator().next(); assertEquals("a", rv.getDescription()); } @Test public void testVariables() throws Exception { rule.setXPath("//VariableDeclaratorId[@Image=$var]"); rule.setMessage("Avoid vars"); StringProperty varDescriptor = new StringProperty("var", "Test var", null, 1.0f); rule.definePropertyDescriptor(varDescriptor); rule.setProperty(varDescriptor, "fiddle"); PMD p = new PMD(); RuleContext ctx = new RuleContext(); Report report = new Report(); ctx.setReport(report); ctx.setSourceCodeFilename("n/a"); RuleSet rules = new RuleSetFactory().createSingleRuleRuleSet(rule); p.getSourceCodeProcessor().processSourceCode(new StringReader(TEST2), new RuleSets(rules), ctx); RuleViolation rv = report.iterator().next(); assertEquals(3, rv.getBeginLine()); } /** * Test for problem reported in bug #1219 PrimarySuffix/@Image does not work * in some cases in xpath 2.0 * * @throws Exception * any error */ @Test public void testImageOfPrimarySuffix() throws Exception { final String SUFFIX = "import java.io.File;\n" + "\n" + "public class TestSuffix {\n" + " public static void main(String args[]) {\n" + " new File(\"subdirectory\").list();\n" + " }\n" + "}"; LanguageVersion language = LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getDefaultVersion(); ParserOptions parserOptions = language.getLanguageVersionHandler().getDefaultParserOptions(); Parser parser = language.getLanguageVersionHandler().getParser(parserOptions); ASTCompilationUnit cu = (ASTCompilationUnit) parser.parse("test", new StringReader(SUFFIX)); RuleContext ruleContext = new RuleContext(); ruleContext.setLanguageVersion(language); String xpath = "//PrimarySuffix[@Image='list']"; // XPATH version 1.0 XPathRuleQuery xpathRuleQuery = new JaxenXPathRuleQuery(); xpathRuleQuery.setXPath(xpath); xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>()); xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_1_0); List<Node> nodes = xpathRuleQuery.evaluate(cu, ruleContext); assertEquals(1, nodes.size()); // XPATH version 1.0 Compatibility xpathRuleQuery = new SaxonXPathRuleQuery(); xpathRuleQuery.setXPath(xpath); xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>()); xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_1_0_COMPATIBILITY); nodes = xpathRuleQuery.evaluate(cu, ruleContext); assertEquals(1, nodes.size()); // XPATH version 2.0 xpathRuleQuery = new SaxonXPathRuleQuery(); xpathRuleQuery.setXPath(xpath); xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>()); xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_2_0); nodes = xpathRuleQuery.evaluate(cu, ruleContext); assertEquals(1, nodes.size()); } /** * Following sibling check: See https://sourceforge.net/p/pmd/bugs/1209/ * * @throws Exception * any error */ @Test public void testFollowingSibling() throws Exception { final String SOURCE = "public class dummy {\n" + " public String toString() {\n" + " String test = \"bad example\";\n" + " test = \"a\";\n" + " return test;\n" + " }\n" + "}"; LanguageVersion language = LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getDefaultVersion(); ParserOptions parserOptions = language.getLanguageVersionHandler().getDefaultParserOptions(); Parser parser = language.getLanguageVersionHandler().getParser(parserOptions); ASTCompilationUnit cu = (ASTCompilationUnit) parser.parse("test", new StringReader(SOURCE)); RuleContext ruleContext = new RuleContext(); ruleContext.setLanguageVersion(language); String xpath = "//Block/BlockStatement/following-sibling::BlockStatement"; // XPATH version 1.0 XPathRuleQuery xpathRuleQuery = new JaxenXPathRuleQuery(); xpathRuleQuery.setXPath(xpath); xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>()); xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_1_0); List<Node> nodes = xpathRuleQuery.evaluate(cu, ruleContext); assertEquals(2, nodes.size()); assertEquals(4, nodes.get(0).getBeginLine()); assertEquals(5, nodes.get(1).getBeginLine()); // XPATH version 2.0 xpathRuleQuery = new SaxonXPathRuleQuery(); xpathRuleQuery.setXPath(xpath); xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>()); xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_2_0); nodes = xpathRuleQuery.evaluate(cu, ruleContext); assertEquals(2, nodes.size()); assertEquals(4, nodes.get(0).getBeginLine()); assertEquals(5, nodes.get(1).getBeginLine()); } private static final String TEST1 = "public class Foo {" + PMD.EOL + " int a;" + PMD.EOL + "}"; private static final String TEST2 = "public class Foo {" + PMD.EOL + " int faddle;" + PMD.EOL + " int fiddle;" + PMD.EOL + "}"; }