KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > test > net > sourceforge > pmd > testframework > RuleTst


1 /**
2  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3  */

4 package test.net.sourceforge.pmd.testframework;
5
6 import java.io.IOException JavaDoc;
7 import java.io.InputStream JavaDoc;
8 import java.io.StringReader JavaDoc;
9 import java.util.Properties JavaDoc;
10
11 import javax.xml.parsers.DocumentBuilder JavaDoc;
12 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
13 import javax.xml.parsers.FactoryConfigurationError JavaDoc;
14 import javax.xml.parsers.ParserConfigurationException JavaDoc;
15
16 import junit.framework.TestCase;
17 import net.sourceforge.pmd.PMD;
18 import net.sourceforge.pmd.PMDException;
19 import net.sourceforge.pmd.Report;
20 import net.sourceforge.pmd.Rule;
21 import net.sourceforge.pmd.RuleContext;
22 import net.sourceforge.pmd.RuleSet;
23 import net.sourceforge.pmd.RuleSetFactory;
24 import net.sourceforge.pmd.RuleSetNotFoundException;
25 import net.sourceforge.pmd.RuleSets;
26 import net.sourceforge.pmd.SimpleRuleSetNameMapper;
27 import net.sourceforge.pmd.SourceType;
28 import net.sourceforge.pmd.SourceTypeToRuleLanguageMapper;
29
30 import org.w3c.dom.Document JavaDoc;
31 import org.w3c.dom.Element JavaDoc;
32 import org.w3c.dom.Node JavaDoc;
33 import org.w3c.dom.NodeList JavaDoc;
34 import org.xml.sax.SAXException JavaDoc;
35
36 /**
37  * Advanced methods for test cases
38  */

39 public class RuleTst extends TestCase {
40     public static final SourceType DEFAULT_SOURCE_TYPE = SourceType.JAVA_14;
41
42     /**
43      * Find a rule in a certain ruleset by name
44      */

45     public Rule findRule(String JavaDoc ruleSet, String JavaDoc ruleName) {
46         try {
47             Rule rule = new RuleSetFactory().createRuleSets(new SimpleRuleSetNameMapper(ruleSet).getRuleSets()).getRuleByName(ruleName);
48             rule.setRuleSetName(ruleSet);
49             if (rule == null) {
50                 fail("Rule " + ruleName + " not found in ruleset " + ruleSet);
51             }
52             return rule;
53         } catch (RuleSetNotFoundException e) {
54             e.printStackTrace();
55             fail("Couldn't find ruleset " + ruleSet);
56             return null;
57         }
58     }
59
60
61     /**
62      * Run the rule on the given code, and check the expected number of violations.
63      */

64     public void runTest(TestDescriptor test) {
65         Rule rule = test.getRule();
66         
67         if (test.getReinitializeRule()) {
68             rule = findRule(rule.getRuleSetName(), rule.getName());
69         }
70         
71         Properties JavaDoc ruleProperties = rule.getProperties();
72         Properties JavaDoc oldProperties = (Properties JavaDoc)ruleProperties.clone();
73         try {
74             if (test.getProperties() != null) {
75                 oldProperties = (Properties JavaDoc)ruleProperties.clone();
76                 ruleProperties.putAll(test.getProperties());
77             }
78             
79             int res = processUsingStringReader(test.getCode(), rule, test.getSourceType()).size();
80             assertEquals("\"" + test.getDescription() + "\" test resulted in wrong number of failures,",
81                 test.getNumberOfProblemsExpected(), res);
82         } catch (Throwable JavaDoc t) {
83             t.printStackTrace();
84             throw new RuntimeException JavaDoc("Test \"" + test.getDescription() + "\" failed");
85         } finally {
86             //Restore old properties
87
ruleProperties.clear();
88             ruleProperties.putAll(oldProperties);
89         }
90     }
91
92     private Report processUsingStringReader(String JavaDoc code, Rule rule,
93                                             SourceType sourceType) throws PMDException {
94         Report report = new Report();
95         runTestFromString(code, rule, report, sourceType);
96         return report;
97     }
98
99     /**
100      * Run the rule on the given code and put the violations in the report.
101      */

102     public void runTestFromString(String JavaDoc code, Rule rule, Report report, SourceType sourceType) throws PMDException {
103         PMD p = new PMD();
104         p.setJavaVersion(sourceType);
105         RuleContext ctx = new RuleContext();
106         ctx.setReport(report);
107         ctx.setSourceCodeFilename("n/a");
108         RuleSet rules = new RuleSet();
109         rules.addRule(rule);
110         rules.setLanguage(SourceTypeToRuleLanguageMapper.getMappedLanguage(sourceType));
111         p.processFile(new StringReader JavaDoc(code), new RuleSets(rules), ctx, sourceType);
112     }
113     
114     /**
115      * getResourceAsStream tries to find the XML file in weird locations if the
116      * ruleName includes the package, so we strip it here.
117      */

118     private String JavaDoc getCleanRuleName(Rule rule) {
119         String JavaDoc fullClassName = rule.getClass().getName();
120         if (fullClassName.equals(rule.getName())) {
121             //We got the full class name, so we'll use the stripped name instead
122
String JavaDoc packageName = rule.getClass().getPackage().getName();
123             return fullClassName.substring(packageName.length()+1);
124         } else {
125             return rule.getName(); //Test is using findRule, smart!
126
}
127     }
128
129     /**
130      * Extract a set of tests from an XML file. The file should be
131      * ./xml/RuleName.xml relative to the test class. The format is defined in
132      * test-data.xsd.
133      */

134     public TestDescriptor[] extractTestsFromXml(Rule rule) {
135         String JavaDoc testsFileName = getCleanRuleName(rule);
136
137         return extractTestsFromXml(rule, testsFileName);
138     }
139
140     /**
141      * Extract a set of tests from an XML file with the given name. The file should be
142      * ./xml/[testsFileName].xml relative to the test class. The format is defined in
143      * test-data.xsd.
144      */

145     public TestDescriptor[] extractTestsFromXml(Rule rule, String JavaDoc testsFileName) {
146         String JavaDoc testXmlFileName = "xml/" + testsFileName + ".xml";
147         InputStream JavaDoc inputStream = getClass().getResourceAsStream(testXmlFileName);
148         if (inputStream == null) {
149             throw new RuntimeException JavaDoc("Couldn't find " + testXmlFileName);
150         }
151         
152         Document JavaDoc doc;
153         try {
154             DocumentBuilder JavaDoc builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
155             doc = builder.parse(inputStream);
156         } catch (ParserConfigurationException JavaDoc pce) {
157             pce.printStackTrace();
158             throw new RuntimeException JavaDoc("Couldn't parse " + testXmlFileName + ", due to: " + pce.getMessage());
159         } catch (FactoryConfigurationError JavaDoc fce) {
160             fce.printStackTrace();
161             throw new RuntimeException JavaDoc("Couldn't parse " + testXmlFileName + ", due to: " + fce.getMessage());
162         } catch (IOException JavaDoc ioe) {
163             ioe.printStackTrace();
164             throw new RuntimeException JavaDoc("Couldn't parse " + testXmlFileName + ", due to: " + ioe.getMessage());
165         } catch (SAXException JavaDoc se) {
166             se.printStackTrace();
167             throw new RuntimeException JavaDoc("Couldn't parse " + testXmlFileName + ", due to: " + se.getMessage());
168         }
169
170         return parseTests(rule, doc);
171     }
172
173     private TestDescriptor[] parseTests(Rule rule, Document JavaDoc doc) {
174         Element JavaDoc root = doc.getDocumentElement();
175         NodeList JavaDoc testCodes = root.getElementsByTagName("test-code");
176
177         TestDescriptor[] tests = new TestDescriptor[testCodes.getLength()];
178         for (int i = 0; i < testCodes.getLength(); i++) {
179             Element JavaDoc testCode = (Element JavaDoc)testCodes.item(i);
180
181             boolean reinitializeRule = false;
182             Node JavaDoc reinitializeRuleAttribute = testCode.getAttributes().getNamedItem("reinitializeRule");
183             if (reinitializeRuleAttribute != null) {
184                 String JavaDoc reinitializeRuleValue = reinitializeRuleAttribute.getNodeValue();
185                 if ("true".equalsIgnoreCase(reinitializeRuleValue) ||
186                         "1".equalsIgnoreCase(reinitializeRuleValue)) {
187                     reinitializeRule = true;
188                 }
189             }
190             
191             NodeList JavaDoc ruleProperties = testCode.getElementsByTagName("rule-property");
192             Properties JavaDoc properties = new Properties JavaDoc();
193             for (int j = 0; j < ruleProperties.getLength(); j++) {
194                 Node JavaDoc ruleProperty = ruleProperties.item(j);
195                 String JavaDoc propertyName = ruleProperty.getAttributes().getNamedItem("name").getNodeValue();
196                 properties.setProperty(propertyName, parseTextNode(ruleProperty));
197             }
198             int expectedProblems = Integer.parseInt(getNodeValue(testCode, "expected-problems", true));
199             String JavaDoc description = getNodeValue(testCode, "description", true);
200             String JavaDoc code = getNodeValue(testCode, "code", false);
201             if (code == null) {
202                 //Should have a coderef
203
NodeList JavaDoc coderefs = testCode.getElementsByTagName("code-ref");
204                 if (coderefs.getLength()==0) {
205                     throw new RuntimeException JavaDoc("Required tag is missing from the test-xml. Supply either a code or a code-ref tag");
206                 }
207                 Node JavaDoc coderef = coderefs.item(0);
208                 String JavaDoc referenceId = coderef.getAttributes().getNamedItem("id").getNodeValue();
209                 NodeList JavaDoc codeFragments = root.getElementsByTagName("code-fragment");
210                 for (int j = 0; j < codeFragments.getLength(); j++) {
211                     String JavaDoc fragmentId = codeFragments.item(j).getAttributes().getNamedItem("id").getNodeValue();
212                     if (referenceId.equals(fragmentId)) {
213                         code = parseTextNode(codeFragments.item(j));
214                     }
215                 }
216                 
217                 if (code==null) {
218                     throw new RuntimeException JavaDoc("No matching code fragment found for coderef");
219                 }
220             }
221             
222             String JavaDoc sourceTypeString = getNodeValue(testCode, "source-type", false);
223             if (sourceTypeString == null) {
224                 tests[i] = new TestDescriptor(code, description, expectedProblems, rule);
225             } else {
226                 SourceType sourceType = SourceType.getSourceTypeForId(sourceTypeString);
227                 if (sourceType != null) {
228                     tests[i] = new TestDescriptor(code, description, expectedProblems, rule, sourceType);
229                 } else {
230                     throw new RuntimeException JavaDoc("Unknown sourceType for test: " + sourceTypeString);
231                 }
232             }
233             tests[i].setReinitializeRule(reinitializeRule);
234             tests[i].setProperties(properties);
235         }
236         return tests;
237     }
238
239     private String JavaDoc getNodeValue(Element JavaDoc parentElm, String JavaDoc nodeName, boolean required) {
240         NodeList JavaDoc nodes = parentElm.getElementsByTagName(nodeName);
241         if (nodes == null || nodes.getLength() == 0) {
242             if (required) {
243                 throw new RuntimeException JavaDoc("Required tag is missing from the test-xml: " + nodeName);
244             } else {
245                 return null;
246             }
247         }
248         Node JavaDoc node = nodes.item(0);
249         return parseTextNode(node);
250     }
251     
252     private static String JavaDoc parseTextNode(Node JavaDoc exampleNode) {
253         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
254         for (int i = 0; i < exampleNode.getChildNodes().getLength(); i++) {
255             Node JavaDoc node = exampleNode.getChildNodes().item(i);
256             if (node.getNodeType() == Node.CDATA_SECTION_NODE
257                     || node.getNodeType() == Node.TEXT_NODE) {
258                 buffer.append(node.getNodeValue());
259             }
260         }
261         return buffer.toString().trim();
262     }
263     
264     /**
265      * Run the test using the DEFAULT_SOURCE_TYPE and put the violations in the report.
266      * Convenience method.
267      */

268     public void runTestFromString(String JavaDoc code, Rule rule, Report report) throws PMDException {
269         runTestFromString(code, rule, report, DEFAULT_SOURCE_TYPE);
270     }
271 }
272
Popular Tags