View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.java.rule;
5    
6   import static org.junit.Assert.assertEquals;
7   
8   import java.io.StringReader;
9   import java.util.HashMap;
10  import java.util.List;
11  
12  import net.sourceforge.pmd.PMD;
13  import net.sourceforge.pmd.PropertyDescriptor;
14  import net.sourceforge.pmd.Report;
15  import net.sourceforge.pmd.RuleContext;
16  import net.sourceforge.pmd.RuleSet;
17  import net.sourceforge.pmd.RuleSets;
18  import net.sourceforge.pmd.RuleViolation;
19  import net.sourceforge.pmd.lang.LanguageRegistry;
20  import net.sourceforge.pmd.lang.LanguageVersion;
21  import net.sourceforge.pmd.lang.Parser;
22  import net.sourceforge.pmd.lang.ParserOptions;
23  import net.sourceforge.pmd.lang.ast.Node;
24  import net.sourceforge.pmd.lang.java.JavaLanguageModule;
25  import net.sourceforge.pmd.lang.java.ast.ASTCompilationUnit;
26  import net.sourceforge.pmd.lang.rule.XPathRule;
27  import net.sourceforge.pmd.lang.rule.properties.StringProperty;
28  import net.sourceforge.pmd.lang.rule.xpath.JaxenXPathRuleQuery;
29  import net.sourceforge.pmd.lang.rule.xpath.SaxonXPathRuleQuery;
30  import net.sourceforge.pmd.lang.rule.xpath.XPathRuleQuery;
31  import net.sourceforge.pmd.testframework.RuleTst;
32  
33  import org.junit.Before;
34  import org.junit.Test;
35  
36   /**
37    * @author daniels
38    */
39   public class XPathRuleTest extends RuleTst {
40   
41       XPathRule rule;
42   
43       @Before
44       public void setUp() {
45           rule = new XPathRule();
46           rule.setLanguage(LanguageRegistry.getLanguage(JavaLanguageModule.NAME));
47           rule.setMessage("XPath Rule Failed");
48       }
49   
50       @Test
51       public void testPluginname() throws Throwable {
52           rule.setXPath("//VariableDeclaratorId[string-length(@Image) < 3]");
53           rule.setMessage("{0}");
54           PMD p = new PMD();
55           RuleContext ctx = new RuleContext();
56           Report report = new Report();
57           ctx.setReport(report);
58           ctx.setSourceCodeFilename("n/a");
59           RuleSet rules = new RuleSet();
60           rules.addRule(rule);
61           p.getSourceCodeProcessor().processSourceCode(new StringReader(TEST1), new RuleSets(rules), ctx);
62           RuleViolation rv = report.iterator().next();
63           assertEquals("a", rv.getDescription());
64       }
65   
66       @Test
67       public void testVariables() throws Throwable {
68           rule.setXPath("//VariableDeclaratorId[@Image=$var]");
69           rule.setMessage("Avoid vars");
70           StringProperty varDescriptor = new StringProperty("var", "Test var", null, 1.0f);
71           rule.definePropertyDescriptor(varDescriptor);
72           rule.setProperty(varDescriptor, "fiddle");
73           PMD p = new PMD();
74           RuleContext ctx = new RuleContext();
75           Report report = new Report();
76           ctx.setReport(report);
77           ctx.setSourceCodeFilename("n/a");
78           RuleSet rules = new RuleSet();
79           rules.addRule(rule);
80           p.getSourceCodeProcessor().processSourceCode(new StringReader(TEST2), new RuleSets(rules), ctx);
81           RuleViolation rv = report.iterator().next();
82           assertEquals(3, rv.getBeginLine());
83       }
84  
85       /**
86        * Test for problem reported in bug #1219 PrimarySuffix/@Image does not work in some cases in xpath 2.0
87        * @throws Exception any error
88        */
89       @Test
90       public void testImageOfPrimarySuffix() throws Exception {
91           String SUFFIX = "import java.io.File;\n" + 
92                   "\n" + 
93                   "public class TestSuffix {\n" + 
94                   "    public static void main(String args[]) {\n" + 
95                   "        new File(\"subdirectory\").list();\n" + 
96                   "    }\n" + 
97                   "}";
98           LanguageVersion language = LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getDefaultVersion();
99           ParserOptions parserOptions = language.getLanguageVersionHandler().getDefaultParserOptions();
100          Parser parser = language.getLanguageVersionHandler().getParser(parserOptions);
101          ASTCompilationUnit cu = (ASTCompilationUnit)parser.parse("test", new StringReader(SUFFIX));
102          RuleContext ruleContext = new RuleContext();
103          ruleContext.setLanguageVersion(language);
104 
105          String xpath = "//PrimarySuffix[@Image='list']";
106 
107          // XPATH version 1.0
108          XPathRuleQuery xpathRuleQuery = new JaxenXPathRuleQuery();
109          xpathRuleQuery.setXPath(xpath);
110          xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>());
111          xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_1_0);
112          List<Node> nodes = xpathRuleQuery.evaluate(cu, ruleContext);
113          assertEquals(1, nodes.size());
114 
115          // XPATH version 1.0 Compatibility
116          xpathRuleQuery = new SaxonXPathRuleQuery();
117          xpathRuleQuery.setXPath(xpath);
118          xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>());
119          xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_1_0_COMPATIBILITY);
120          nodes = xpathRuleQuery.evaluate(cu, ruleContext);
121          assertEquals(1, nodes.size());
122 
123          // XPATH version 2.0
124          xpathRuleQuery = new SaxonXPathRuleQuery();
125          xpathRuleQuery.setXPath(xpath);
126          xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>());
127          xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_2_0);
128          nodes = xpathRuleQuery.evaluate(cu, ruleContext);
129          assertEquals(1, nodes.size());
130      }
131 
132      /**
133       * Following sibling check: See https://sourceforge.net/p/pmd/bugs/1209/
134       * @throws Exception any error
135       */
136      @Test
137      public void testFollowingSibling() throws Exception {
138          String SOURCE = "public class dummy {\n" +
139                  "  public String toString() {\n" +
140                  "    String test = \"bad example\";\n" +
141                  "    test = \"a\";\n" +
142                  "    return test;\n" +
143                  "  }\n" +
144                  "}";
145          LanguageVersion language = LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getDefaultVersion();
146          ParserOptions parserOptions = language.getLanguageVersionHandler().getDefaultParserOptions();
147          Parser parser = language.getLanguageVersionHandler().getParser(parserOptions);
148          ASTCompilationUnit cu = (ASTCompilationUnit)parser.parse("test", new StringReader(SOURCE));
149          RuleContext ruleContext = new RuleContext();
150          ruleContext.setLanguageVersion(language);
151 
152          String xpath = "//Block/BlockStatement/following-sibling::BlockStatement";
153 
154          // XPATH version 1.0
155          XPathRuleQuery xpathRuleQuery = new JaxenXPathRuleQuery();
156          xpathRuleQuery.setXPath(xpath);
157          xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>());
158          xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_1_0);
159          List<Node> nodes = xpathRuleQuery.evaluate(cu, ruleContext);
160          assertEquals(2, nodes.size());
161          assertEquals(4, nodes.get(0).getBeginLine());
162          assertEquals(5, nodes.get(1).getBeginLine());
163 
164          // XPATH version 2.0
165          xpathRuleQuery = new SaxonXPathRuleQuery();
166          xpathRuleQuery.setXPath(xpath);
167          xpathRuleQuery.setProperties(new HashMap<PropertyDescriptor<?>, Object>());
168          xpathRuleQuery.setVersion(XPathRuleQuery.XPATH_2_0);
169          nodes = xpathRuleQuery.evaluate(cu, ruleContext);
170          assertEquals(2, nodes.size());
171          assertEquals(4, nodes.get(0).getBeginLine());
172          assertEquals(5, nodes.get(1).getBeginLine());
173      }
174 
175      private static final String TEST1 =
176              "public class Foo {" + PMD.EOL +
177              " int a;" + PMD.EOL +
178              "}";
179  
180      private static final String TEST2 =
181              "public class Foo {" + PMD.EOL +
182              " int faddle;" + PMD.EOL +
183              " int fiddle;" + PMD.EOL +
184              "}";
185 
186      public static junit.framework.Test suite() {
187          return new junit.framework.JUnit4TestAdapter(XPathRuleTest.class);
188      }
189  }