1
2
3
4 package net.sourceforge.pmd;
5
6 import static org.junit.Assert.assertEquals;
7 import static org.junit.Assert.assertFalse;
8 import static org.junit.Assert.assertNotNull;
9 import static org.junit.Assert.assertNotSame;
10 import static org.junit.Assert.assertNull;
11 import static org.junit.Assert.assertTrue;
12 import static org.junit.Assert.fail;
13
14 import java.io.BufferedReader;
15 import java.io.ByteArrayInputStream;
16 import java.io.ByteArrayOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.InputStreamReader;
20 import java.util.ArrayList;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Properties;
24 import java.util.Set;
25 import java.util.StringTokenizer;
26
27 import javax.xml.parsers.ParserConfigurationException;
28 import javax.xml.parsers.SAXParser;
29 import javax.xml.parsers.SAXParserFactory;
30
31 import junit.framework.JUnit4TestAdapter;
32 import net.sourceforge.pmd.lang.Language;
33 import net.sourceforge.pmd.lang.LanguageVersion;
34 import net.sourceforge.pmd.lang.java.rule.unusedcode.UnusedLocalVariableRule;
35 import net.sourceforge.pmd.lang.rule.RuleReference;
36 import net.sourceforge.pmd.lang.rule.XPathRule;
37 import net.sourceforge.pmd.util.ResourceLoader;
38
39 import org.junit.BeforeClass;
40 import org.junit.Test;
41 import org.xml.sax.InputSource;
42 import org.xml.sax.SAXException;
43 import org.xml.sax.SAXParseException;
44 import org.xml.sax.helpers.DefaultHandler;
45
46 public class RuleSetFactoryTest {
47 private static SAXParserFactory saxParserFactory;
48 private static ValidateDefaultHandler validateDefaultHandlerXsd;
49 private static ValidateDefaultHandler validateDefaultHandlerDtd;
50 private static SAXParser saxParser;
51
52 @BeforeClass
53 public static void init() throws Exception {
54 saxParserFactory = SAXParserFactory.newInstance();
55 saxParserFactory.setValidating(true);
56 saxParserFactory.setNamespaceAware(true);
57
58
59
60
61 saxParserFactory.setFeature("http://xml.org/sax/features/validation",
62 true);
63 saxParserFactory.setFeature(
64 "http://apache.org/xml/features/validation/schema", true);
65 saxParserFactory
66 .setFeature(
67 "http://apache.org/xml/features/validation/schema-full-checking",
68 true);
69
70 validateDefaultHandlerXsd = new ValidateDefaultHandler("src/main/resources/ruleset_2_0_0.xsd");
71 validateDefaultHandlerDtd = new ValidateDefaultHandler("src/main/resources/ruleset_2_0_0.dtd");
72
73 saxParser = saxParserFactory.newSAXParser();
74 }
75
76 @Test
77 public void testRuleSetFileName() throws RuleSetNotFoundException {
78 RuleSet rs = loadRuleSet(EMPTY_RULESET);
79 assertNull("RuleSet file name not expected", rs.getFileName());
80
81 RuleSetFactory rsf = new RuleSetFactory();
82 rs = rsf.createRuleSet("rulesets/java/basic.xml");
83 assertEquals("wrong RuleSet file name", rs.getFileName(),
84 "rulesets/java/basic.xml");
85 }
86
87 @Test
88 public void testNoRuleSetFileName() throws RuleSetNotFoundException {
89 RuleSet rs = loadRuleSet(EMPTY_RULESET);
90 assertNull("RuleSet file name not expected", rs.getFileName());
91 }
92
93 @Test
94 public void testRefs() throws Throwable {
95 InputStream in = ResourceLoader.loadResourceAsStream(
96 "rulesets/java/migrating_to_15.xml", this.getClass()
97 .getClassLoader());
98 if (in == null) {
99 throw new RuleSetNotFoundException(
100 "Can't find resource Make sure the resource is a valid file or URL or is on the CLASSPATH. Here's the current classpath: "
101 + System.getProperty("java.class.path"));
102 }
103 RuleSetFactory rsf = new RuleSetFactory();
104 RuleSet rs = rsf.createRuleSet("rulesets/java/migrating_to_15.xml");
105 assertNotNull(rs.getRuleByName("AvoidEnumAsIdentifier"));
106 }
107
108 @Test(expected = RuleSetNotFoundException.class)
109 public void testRuleSetNotFound() throws RuleSetNotFoundException {
110 RuleSetFactory rsf = new RuleSetFactory();
111 rsf.createRuleSet("fooooo");
112 }
113
114 @Test
115 public void testCreateEmptyRuleSet() throws RuleSetNotFoundException {
116 RuleSet rs = loadRuleSet(EMPTY_RULESET);
117 assertEquals("test", rs.getName());
118 assertEquals(0, rs.size());
119 }
120
121 @Test
122 public void testSingleRule() throws RuleSetNotFoundException {
123 RuleSet rs = loadRuleSet(SINGLE_RULE);
124 assertEquals(1, rs.size());
125 Rule r = rs.getRules().iterator().next();
126 assertEquals("MockRuleName", r.getName());
127 assertEquals("net.sourceforge.pmd.lang.rule.MockRule", r.getRuleClass());
128 assertEquals("avoid the mock rule", r.getMessage());
129 }
130
131 @Test
132 public void testMultipleRules() throws RuleSetNotFoundException {
133 RuleSet rs = loadRuleSet(MULTIPLE_RULES);
134 assertEquals(2, rs.size());
135 Set<String> expected = new HashSet<String>();
136 expected.add("MockRuleName1");
137 expected.add("MockRuleName2");
138 for (Rule rule : rs.getRules()) {
139 assertTrue(expected.contains(rule.getName()));
140 }
141 }
142
143 @Test
144 public void testSingleRuleWithPriority() throws RuleSetNotFoundException {
145 assertEquals(RulePriority.MEDIUM, loadFirstRule(PRIORITY).getPriority());
146 }
147
148 @Test
149 @SuppressWarnings("unchecked")
150 public void testProps() throws RuleSetNotFoundException {
151 Rule r = loadFirstRule(PROPERTIES);
152 assertEquals("bar", r.getProperty((PropertyDescriptor<String>) r.getPropertyDescriptor("fooString")));
153 assertEquals(new Integer(3), r.getProperty((PropertyDescriptor<Integer>) r.getPropertyDescriptor("fooInt")));
154 assertTrue(r.getProperty((PropertyDescriptor<Boolean>) r.getPropertyDescriptor("fooBoolean")));
155 assertEquals(3.0d, r.getProperty((PropertyDescriptor<Double>) r.getPropertyDescriptor("fooDouble")), 0.05);
156 assertNull(r.getPropertyDescriptor("BuggleFish"));
157 assertNotSame(r.getDescription().indexOf("testdesc2"), -1);
158 }
159
160 @Test
161 @SuppressWarnings("unchecked")
162 public void testXPath() throws RuleSetNotFoundException {
163 Rule r = loadFirstRule(XPATH);
164 PropertyDescriptor<String> xpathProperty = (PropertyDescriptor<String>) r.getPropertyDescriptor("xpath");
165 assertNotNull("xpath property descriptor", xpathProperty);
166 assertNotSame(r.getProperty(xpathProperty).indexOf(" //Block "), -1);
167 }
168
169 @Test
170 public void testFacadesOffByDefault() throws RuleSetNotFoundException {
171 Rule r = loadFirstRule(XPATH);
172 assertFalse(r.usesDFA());
173 }
174
175 @Test
176 public void testDFAFlag() throws RuleSetNotFoundException {
177 assertTrue(loadFirstRule(DFA).usesDFA());
178 }
179
180 @Test
181 public void testExternalReferenceOverride() throws RuleSetNotFoundException {
182 Rule r = loadFirstRule(REF_OVERRIDE);
183 assertEquals("TestNameOverride", r.getName());
184 assertEquals("Test message override", r.getMessage());
185 assertEquals("Test description override", r.getDescription());
186 assertEquals("Test that both example are stored", 2, r.getExamples().size());
187 assertEquals("Test example override", r.getExamples().get(1));
188 assertEquals(RulePriority.MEDIUM, r.getPriority());
189 PropertyDescriptor<?> test2Descriptor = r.getPropertyDescriptor("test2");
190 assertNotNull("test2 descriptor", test2Descriptor);
191 assertEquals("override2", r.getProperty(test2Descriptor));
192 PropertyDescriptor<?> test3Descriptor = r.getPropertyDescriptor("test3");
193 assertNotNull("test3 descriptor", test3Descriptor);
194 assertEquals("override3", r.getProperty(test3Descriptor));
195 PropertyDescriptor<?> test4Descriptor = r.getPropertyDescriptor("test4");
196 assertNotNull("test3 descriptor", test4Descriptor);
197 assertEquals("new property", r.getProperty(test4Descriptor));
198 }
199
200 @Test
201 public void testReferenceInternalToInternal()
202 throws RuleSetNotFoundException {
203 RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_INTERNAL);
204
205 Rule rule = ruleSet.getRuleByName("MockRuleName");
206 assertNotNull("Could not find Rule MockRuleName", rule);
207
208 Rule ruleRef = ruleSet.getRuleByName("MockRuleNameRef");
209 assertNotNull("Could not find Rule MockRuleNameRef", ruleRef);
210 }
211
212 @Test
213 public void testReferenceInternalToInternalChain()
214 throws RuleSetNotFoundException {
215 RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_INTERNAL_CHAIN);
216
217 Rule rule = ruleSet.getRuleByName("MockRuleName");
218 assertNotNull("Could not find Rule MockRuleName", rule);
219
220 Rule ruleRef = ruleSet.getRuleByName("MockRuleNameRef");
221 assertNotNull("Could not find Rule MockRuleNameRef", ruleRef);
222
223 Rule ruleRefRef = ruleSet.getRuleByName("MockRuleNameRefRef");
224 assertNotNull("Could not find Rule MockRuleNameRefRef", ruleRefRef);
225 }
226
227 @Test
228 public void testReferenceInternalToExternal()
229 throws RuleSetNotFoundException {
230 RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_EXTERNAL);
231
232 Rule rule = ruleSet.getRuleByName("ExternalRefRuleName");
233 assertNotNull("Could not find Rule ExternalRefRuleName", rule);
234
235 Rule ruleRef = ruleSet.getRuleByName("ExternalRefRuleNameRef");
236 assertNotNull("Could not find Rule ExternalRefRuleNameRef", ruleRef);
237 }
238
239 @Test
240 public void testReferenceInternalToExternalChain()
241 throws RuleSetNotFoundException {
242 RuleSet ruleSet = loadRuleSet(REF_INTERNAL_TO_EXTERNAL_CHAIN);
243
244 Rule rule = ruleSet.getRuleByName("ExternalRefRuleName");
245 assertNotNull("Could not find Rule ExternalRefRuleName", rule);
246
247 Rule ruleRef = ruleSet.getRuleByName("ExternalRefRuleNameRef");
248 assertNotNull("Could not find Rule ExternalRefRuleNameRef", ruleRef);
249
250 Rule ruleRefRef = ruleSet.getRuleByName("ExternalRefRuleNameRefRef");
251 assertNotNull("Could not find Rule ExternalRefRuleNameRefRef",
252 ruleRefRef);
253 }
254
255 @Test
256 public void testReferencePriority() throws RuleSetNotFoundException {
257 RuleSetFactory rsf = new RuleSetFactory();
258
259 rsf.setMinimumPriority(RulePriority.LOW);
260 RuleSet ruleSet = rsf
261 .createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
262 assertEquals("Number of Rules", 3, ruleSet.getRules().size());
263 assertNotNull(ruleSet.getRuleByName("MockRuleName"));
264 assertNotNull(ruleSet.getRuleByName("MockRuleNameRef"));
265 assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
266
267 rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
268 ruleSet = rsf
269 .createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
270 assertEquals("Number of Rules", 2, ruleSet.getRules().size());
271 assertNotNull(ruleSet.getRuleByName("MockRuleNameRef"));
272 assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
273
274 rsf.setMinimumPriority(RulePriority.HIGH);
275 ruleSet = rsf
276 .createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_INTERNAL_CHAIN));
277 assertEquals("Number of Rules", 1, ruleSet.getRules().size());
278 assertNotNull(ruleSet.getRuleByName("MockRuleNameRefRef"));
279
280 rsf.setMinimumPriority(RulePriority.LOW);
281 ruleSet = rsf
282 .createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
283 assertEquals("Number of Rules", 3, ruleSet.getRules().size());
284 assertNotNull(ruleSet.getRuleByName("ExternalRefRuleName"));
285 assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef"));
286 assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
287
288 rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
289 ruleSet = rsf
290 .createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
291 assertEquals("Number of Rules", 2, ruleSet.getRules().size());
292 assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRef"));
293 assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
294
295 rsf.setMinimumPriority(RulePriority.HIGH);
296 ruleSet = rsf
297 .createRuleSet(createRuleSetReferenceId(REF_INTERNAL_TO_EXTERNAL_CHAIN));
298 assertEquals("Number of Rules", 1, ruleSet.getRules().size());
299 assertNotNull(ruleSet.getRuleByName("ExternalRefRuleNameRefRef"));
300 }
301
302 @Test
303 public void testOverrideMessage() throws RuleSetNotFoundException {
304 Rule r = loadFirstRule(REF_OVERRIDE_ORIGINAL_NAME);
305 assertEquals("TestMessageOverride", r.getMessage());
306 }
307
308 @Test
309 public void testOverrideMessageOneElem() throws RuleSetNotFoundException {
310 Rule r = loadFirstRule(REF_OVERRIDE_ORIGINAL_NAME_ONE_ELEM);
311 assertEquals("TestMessageOverride", r.getMessage());
312 }
313
314 @Test(expected = IllegalArgumentException.class)
315 public void testIncorrectExternalRef() throws IllegalArgumentException,
316 RuleSetNotFoundException {
317 loadFirstRule(REF_MISPELLED_XREF);
318 }
319
320 @Test
321 public void testSetPriority() throws RuleSetNotFoundException {
322 RuleSetFactory rsf = new RuleSetFactory();
323 rsf.setMinimumPriority(RulePriority.MEDIUM_HIGH);
324 assertEquals(0, rsf
325 .createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size());
326 rsf.setMinimumPriority(RulePriority.MEDIUM_LOW);
327 assertEquals(1, rsf
328 .createRuleSet(createRuleSetReferenceId(SINGLE_RULE)).size());
329 }
330
331 @Test
332 public void testLanguage() throws RuleSetNotFoundException {
333 Rule r = loadFirstRule(LANGUAGE);
334 assertEquals(Language.JAVA, r.getLanguage());
335 }
336
337 @Test(expected = IllegalArgumentException.class)
338 public void testIncorrectLanguage() throws RuleSetNotFoundException {
339 loadFirstRule(INCORRECT_LANGUAGE);
340 }
341
342 @Test
343 public void testMinimumLanugageVersion() throws RuleSetNotFoundException {
344 Rule r = loadFirstRule(MINIMUM_LANGUAGE_VERSION);
345 assertEquals(LanguageVersion.JAVA_14, r.getMinimumLanguageVersion());
346 }
347
348 @Test(expected = IllegalArgumentException.class)
349 public void testIncorrectMinimumLanugageVersion()
350 throws RuleSetNotFoundException {
351 loadFirstRule(INCORRECT_MINIMUM_LANGUAGE_VERSION);
352 }
353
354 @Test
355 public void testMaximumLanugageVersion() throws RuleSetNotFoundException {
356 Rule r = loadFirstRule(MAXIMUM_LANGUAGE_VERSION);
357 assertEquals(LanguageVersion.JAVA_17, r.getMaximumLanguageVersion());
358 }
359
360 @Test(expected = IllegalArgumentException.class)
361 public void testIncorrectMaximumLanugageVersion()
362 throws RuleSetNotFoundException {
363 loadFirstRule(INCORRECT_MAXIMUM_LANGUAGE_VERSION);
364 }
365
366 @Test(expected = IllegalArgumentException.class)
367 public void testInvertedMinimumMaximumLanugageVersions()
368 throws RuleSetNotFoundException {
369 loadFirstRule(INVERTED_MINIMUM_MAXIMUM_LANGUAGE_VERSIONS);
370 }
371
372 @Test
373 public void testDirectDeprecatedRule() throws RuleSetNotFoundException {
374 Rule r = loadFirstRule(DIRECT_DEPRECATED_RULE);
375 assertNotNull("Direct Deprecated Rule", r);
376 }
377
378 @Test
379 public void testReferenceToDeprecatedRule() throws RuleSetNotFoundException {
380 Rule r = loadFirstRule(REFERENCE_TO_DEPRECATED_RULE);
381 assertNotNull("Reference to Deprecated Rule", r);
382 assertTrue("Rule Reference", r instanceof RuleReference);
383 assertFalse("Not deprecated", r.isDeprecated());
384 assertTrue("Original Rule Deprecated", ((RuleReference) r).getRule()
385 .isDeprecated());
386 assertEquals("Rule name", r.getName(), DEPRECATED_RULE_NAME);
387 }
388
389 @Test
390 public void testRuleSetReferenceWithDeprecatedRule()
391 throws RuleSetNotFoundException {
392 RuleSet ruleSet = loadRuleSet(REFERENCE_TO_RULESET_WITH_DEPRECATED_RULE);
393 assertNotNull("RuleSet", ruleSet);
394 assertFalse("RuleSet empty", ruleSet.getRules().isEmpty());
395
396
397 Rule r = ruleSet.getRuleByName(DEPRECATED_RULE_NAME);
398 assertNull("Deprecated Rule Reference", r);
399 for (Rule rule : ruleSet.getRules()) {
400 assertFalse("Rule not deprecated", rule.isDeprecated());
401 }
402 }
403
404 @Test
405 public void testExternalReferences() throws RuleSetNotFoundException {
406 RuleSet rs = loadRuleSet(EXTERNAL_REFERENCE_RULE_SET);
407 assertEquals(1, rs.size());
408 assertEquals(UnusedLocalVariableRule.class.getName(), rs.getRuleByName(
409 "UnusedLocalVariable").getRuleClass());
410 }
411
412 @Test
413 public void testIncludeExcludePatterns() throws RuleSetNotFoundException {
414 RuleSet ruleSet = loadRuleSet(INCLUDE_EXCLUDE_RULESET);
415
416 assertNotNull("Include patterns", ruleSet.getIncludePatterns());
417 assertEquals("Include patterns size", 2, ruleSet.getIncludePatterns()
418 .size());
419 assertEquals("Include pattern #1", "include1", ruleSet
420 .getIncludePatterns().get(0));
421 assertEquals("Include pattern #2", "include2", ruleSet
422 .getIncludePatterns().get(1));
423
424 assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
425 assertEquals("Exclude patterns size", 3, ruleSet.getExcludePatterns()
426 .size());
427 assertEquals("Exclude pattern #1", "exclude1", ruleSet
428 .getExcludePatterns().get(0));
429 assertEquals("Exclude pattern #2", "exclude2", ruleSet
430 .getExcludePatterns().get(1));
431 assertEquals("Exclude pattern #3", "exclude3", ruleSet
432 .getExcludePatterns().get(2));
433 }
434
435 @Test
436 public void testAllPMDBuiltInRulesMeetConventions() throws IOException,
437 RuleSetNotFoundException, ParserConfigurationException,
438 SAXException {
439 int invalidSinceAttributes = 0;
440 int invalidExternalInfoURL = 0;
441 int invalidClassName = 0;
442 int invalidRegexSuppress = 0;
443 int invalidXPathSuppress = 0;
444 String messages = "";
445
446 List<String> ruleSetFileNames = getRuleSetFileNames();
447 for (String fileName : ruleSetFileNames) {
448 RuleSet ruleSet = loadRuleSetByFileName(fileName);
449 for (Rule rule : ruleSet.getRules()) {
450
451
452 if (rule instanceof RuleReference) {
453 continue;
454 }
455
456 Language language = Language.JAVA;
457 String group = fileName
458 .substring(fileName.lastIndexOf('/') + 1);
459 group = group.substring(0, group.indexOf(".xml"));
460 if (group.indexOf('-') >= 0) {
461 group = group.substring(0, group.indexOf('-'));
462 }
463
464
465 if (rule.getSince() == null) {
466 invalidSinceAttributes++;
467 messages += "Rule " + fileName + "/" + rule.getName()
468 + " is missing 'since' attribute" + PMD.EOL;
469 }
470
471 if (rule.getExternalInfoUrl() == null
472 || "".equalsIgnoreCase(rule.getExternalInfoUrl())) {
473 invalidExternalInfoURL++;
474 messages += "Rule " + fileName + "/" + rule.getName()
475 + " is missing 'externalInfoURL' attribute"
476 + PMD.EOL;
477 } else {
478 String expectedExternalInfoURL = "http://pmd.sourceforge.net/.+/rules/"
479 + fileName.replaceAll("rulesets/", "").replaceAll(
480 ".xml", "") + ".html#" + rule.getName();
481 if (rule.getExternalInfoUrl() == null
482 || !rule.getExternalInfoUrl().matches(expectedExternalInfoURL)) {
483 invalidExternalInfoURL++;
484 messages += "Rule "
485 + fileName
486 + "/"
487 + rule.getName()
488 + " seems to have an invalid 'externalInfoURL' value ("
489 + rule.getExternalInfoUrl()
490 + "), it should be:" + expectedExternalInfoURL
491 + PMD.EOL;
492 }
493 }
494
495 String expectedClassName = "net.sourceforge.pmd.lang."
496 + language.getTerseName() + ".rule." + group + "."
497 + rule.getName() + "Rule";
498 if (!rule.getRuleClass().equals(expectedClassName)
499 && !rule.getRuleClass().equals(
500 XPathRule.class.getName())) {
501 invalidClassName++;
502 messages += "Rule " + fileName + "/" + rule.getName()
503 + " seems to have an invalid 'class' value ("
504 + rule.getRuleClass() + "), it should be:"
505 + expectedClassName + PMD.EOL;
506 }
507
508 if (rule.getProperty(Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR) != null) {
509 invalidRegexSuppress++;
510 messages += "Rule "
511 + fileName
512 + "/"
513 + rule.getName()
514 + " should not have '"
515 + Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR.name()
516 + "', this is intended for end user customization only."
517 + PMD.EOL;
518 }
519
520 if (rule.getProperty(Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR) != null) {
521 invalidXPathSuppress++;
522 messages += "Rule "
523 + fileName
524 + "/"
525 + rule.getName()
526 + " should not have '"
527 + Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR.name()
528 + "', this is intended for end user customization only."
529 + PMD.EOL;
530 }
531 }
532 }
533
534
535 if (invalidSinceAttributes > 0 || invalidExternalInfoURL > 0
536 || invalidClassName > 0 || invalidRegexSuppress > 0
537 || invalidXPathSuppress > 0) {
538 fail("All built-in PMD rules need 'since' attribute ("
539 + invalidSinceAttributes
540 + " are missing), a proper ExternalURLInfo ("
541 + invalidExternalInfoURL
542 + " are invalid), a class name meeting conventions ("
543 + invalidClassName + " are invalid), no '"
544 + Rule.VIOLATION_SUPPRESS_REGEX_DESCRIPTOR.name()
545 + "' property (" + invalidRegexSuppress
546 + " are invalid), and no '"
547 + Rule.VIOLATION_SUPPRESS_XPATH_DESCRIPTOR.name()
548 + "' property (" + invalidXPathSuppress + " are invalid)"
549 + PMD.EOL + messages);
550 }
551 }
552
553 @Test
554 public void testXmlSchema() throws IOException, RuleSetNotFoundException,
555 ParserConfigurationException, SAXException {
556 boolean allValid = true;
557 List<String> ruleSetFileNames = getRuleSetFileNames();
558 for (String fileName : ruleSetFileNames) {
559 boolean valid = validateAgainstSchema(fileName);
560 allValid = allValid && valid;
561 }
562 assertTrue("All XML must parse without producing validation messages.",
563 allValid);
564 }
565
566 @Test
567 public void testDtd() throws IOException, RuleSetNotFoundException,
568 ParserConfigurationException, SAXException {
569 boolean allValid = true;
570 List<String> ruleSetFileNames = getRuleSetFileNames();
571 for (String fileName : ruleSetFileNames) {
572 boolean valid = validateAgainstDtd(fileName);
573 allValid = allValid && valid;
574 }
575 assertTrue("All XML must parse without producing validation messages.",
576 allValid);
577 }
578
579 @Test
580 public void testReadWriteRoundTrip() throws IOException,
581 RuleSetNotFoundException, ParserConfigurationException,
582 SAXException {
583
584 List<String> ruleSetFileNames = getRuleSetFileNames();
585 for (String fileName : ruleSetFileNames) {
586 testRuleSet(fileName);
587 }
588 }
589
590 public void testRuleSet(String fileName) throws IOException,
591 RuleSetNotFoundException, ParserConfigurationException,
592 SAXException {
593
594
595
596
597
598
599 RuleSet ruleSet1 = loadRuleSetByFileName(fileName);
600
601
602 ByteArrayOutputStream outputStream1 = new ByteArrayOutputStream();
603 RuleSetWriter writer1 = new RuleSetWriter(outputStream1);
604 writer1.write(ruleSet1);
605 writer1.close();
606 String xml2 = new String(outputStream1.toByteArray());
607
608
609
610 RuleSetFactory ruleSetFactory = new RuleSetFactory();
611 RuleSet ruleSet2 = ruleSetFactory
612 .createRuleSet(createRuleSetReferenceId(xml2));
613
614
615
616
617 ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
618 RuleSetWriter writer2 = new RuleSetWriter(outputStream2);
619 writer2.write(ruleSet2);
620 writer2.close();
621 String xml3 = new String(outputStream2.toByteArray());
622
623
624
625 RuleSet ruleSet3 = ruleSetFactory
626 .createRuleSet(createRuleSetReferenceId(xml3));
627
628
629 assertTrue(
630 "1st roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")",
631 validateAgainstSchema(new ByteArrayInputStream(xml2.getBytes())));
632 assertTrue(
633 "2nd roundtrip RuleSet XML is not valid against Schema (filename: " + fileName + ")",
634 validateAgainstSchema(new ByteArrayInputStream(xml3.getBytes())));
635 assertTrue("1st roundtrip RuleSet XML is not valid against DTD (filename: " + fileName + ")",
636 validateAgainstDtd(new ByteArrayInputStream(xml2.getBytes())));
637 assertTrue("2nd roundtrip RuleSet XML is not valid against DTD (filename: " + fileName + ")",
638 validateAgainstDtd(new ByteArrayInputStream(xml3.getBytes())));
639
640
641 assertEqualsRuleSet(
642 "Original RuleSet and 1st roundtrip Ruleset not the same (filename: " + fileName + ")",
643 ruleSet1, ruleSet2);
644 assertEqualsRuleSet(
645 "1st roundtrip Ruleset and 2nd roundtrip RuleSet not the same (filename: " + fileName + ")",
646 ruleSet2, ruleSet3);
647
648
649
650 assertEquals("1st roundtrip RuleSet XML and 2nd roundtrip RuleSet XML (filename: " + fileName + ")",
651 xml2, xml3);
652 }
653
654 private void assertEqualsRuleSet(String message, RuleSet ruleSet1,
655 RuleSet ruleSet2) {
656 assertEquals(message + ", RuleSet name", ruleSet1.getName(), ruleSet2
657 .getName());
658 assertEquals(message + ", RuleSet description", ruleSet1
659 .getDescription(), ruleSet2.getDescription());
660 assertEquals(message + ", RuleSet exclude patterns", ruleSet1
661 .getExcludePatterns(), ruleSet2.getExcludePatterns());
662 assertEquals(message + ", RuleSet include patterns", ruleSet1
663 .getIncludePatterns(), ruleSet2.getIncludePatterns());
664 assertEquals(message + ", RuleSet rule count", ruleSet1.getRules()
665 .size(), ruleSet2.getRules().size());
666
667 for (int i = 0; i < ruleSet1.getRules().size(); i++) {
668 Rule rule1 = ((List<Rule>) ruleSet1.getRules()).get(i);
669 Rule rule2 = ((List<Rule>) ruleSet2.getRules()).get(i);
670
671 assertFalse(message + ", Different RuleReference",
672 rule1 instanceof RuleReference
673 && !(rule2 instanceof RuleReference)
674 || !(rule1 instanceof RuleReference)
675 && rule2 instanceof RuleReference);
676
677 if (rule1 instanceof RuleReference) {
678 RuleReference ruleReference1 = (RuleReference) rule1;
679 RuleReference ruleReference2 = (RuleReference) rule2;
680 assertEquals(message + ", RuleReference overridden language",
681 ruleReference1.getOverriddenLanguage(), ruleReference2
682 .getOverriddenLanguage());
683 assertEquals(
684 message
685 + ", RuleReference overridden minimum language version",
686 ruleReference1.getOverriddenMinimumLanguageVersion(),
687 ruleReference2.getOverriddenMinimumLanguageVersion());
688 assertEquals(
689 message
690 + ", RuleReference overridden maximum language version",
691 ruleReference1.getOverriddenMaximumLanguageVersion(),
692 ruleReference2.getOverriddenMaximumLanguageVersion());
693 assertEquals(message + ", RuleReference overridden deprecated",
694 ruleReference1.isOverriddenDeprecated(), ruleReference2
695 .isOverriddenDeprecated());
696 assertEquals(message + ", RuleReference overridden name",
697 ruleReference1.getOverriddenName(), ruleReference2
698 .getOverriddenName());
699 assertEquals(
700 message + ", RuleReference overridden description",
701 ruleReference1.getOverriddenDescription(),
702 ruleReference2.getOverriddenDescription());
703 assertEquals(message + ", RuleReference overridden message",
704 ruleReference1.getOverriddenMessage(), ruleReference2
705 .getOverriddenMessage());
706 assertEquals(message
707 + ", RuleReference overridden external info url",
708 ruleReference1.getOverriddenExternalInfoUrl(),
709 ruleReference2.getOverriddenExternalInfoUrl());
710 assertEquals(message + ", RuleReference overridden priority",
711 ruleReference1.getOverriddenPriority(), ruleReference2
712 .getOverriddenPriority());
713 assertEquals(message + ", RuleReference overridden examples",
714 ruleReference1.getOverriddenExamples(), ruleReference2
715 .getOverriddenExamples());
716 }
717
718 assertEquals(message + ", Rule name", rule1.getName(), rule2
719 .getName());
720 assertEquals(message + ", Rule class", rule1.getRuleClass(), rule2
721 .getRuleClass());
722 assertEquals(message + ", Rule description " + rule1.getName(),
723 rule1.getDescription(), rule2.getDescription());
724 assertEquals(message + ", Rule message", rule1.getMessage(), rule2
725 .getMessage());
726 assertEquals(message + ", Rule external info url", rule1
727 .getExternalInfoUrl(), rule2.getExternalInfoUrl());
728 assertEquals(message + ", Rule priority", rule1.getPriority(),
729 rule2.getPriority());
730 assertEquals(message + ", Rule examples", rule1.getExamples(),
731 rule2.getExamples());
732
733 List<PropertyDescriptor<?>> propertyDescriptors1 = rule1
734 .getPropertyDescriptors();
735 List<PropertyDescriptor<?>> propertyDescriptors2 = rule2
736 .getPropertyDescriptors();
737 try {
738 assertEquals(message + ", Rule property descriptor ",
739 propertyDescriptors1, propertyDescriptors2);
740 } catch (Error e) {
741 throw e;
742 }
743 for (int j = 0; j < propertyDescriptors1.size(); j++) {
744 assertEquals(message + ", Rule property value " + j, rule1
745 .getProperty(propertyDescriptors1.get(j)), rule2
746 .getProperty(propertyDescriptors2.get(j)));
747 }
748 assertEquals(message + ", Rule property descriptor count",
749 propertyDescriptors1.size(), propertyDescriptors2.size());
750 }
751 }
752
753 private boolean validateAgainstSchema(String fileName) throws IOException,
754 RuleSetNotFoundException, ParserConfigurationException,
755 SAXException {
756 InputStream inputStream = loadResourceAsStream(fileName);
757 boolean valid = validateAgainstSchema(inputStream);
758 if (!valid) {
759 System.err.println("Validation against XML Schema failed for: "
760 + fileName);
761 }
762 return valid;
763 }
764
765 private boolean validateAgainstSchema(InputStream inputStream)
766 throws IOException, RuleSetNotFoundException,
767 ParserConfigurationException, SAXException {
768
769 saxParser.parse(inputStream, validateDefaultHandlerXsd.resetValid());
770 inputStream.close();
771 return validateDefaultHandlerXsd.isValid();
772 }
773
774 private boolean validateAgainstDtd(String fileName) throws IOException,
775 RuleSetNotFoundException, ParserConfigurationException,
776 SAXException {
777 InputStream inputStream = loadResourceAsStream(fileName);
778 boolean valid = validateAgainstDtd(inputStream);
779 if (!valid) {
780 System.err
781 .println("Validation against DTD failed for: " + fileName);
782 }
783 return valid;
784 }
785
786 private boolean validateAgainstDtd(InputStream inputStream)
787 throws IOException, RuleSetNotFoundException,
788 ParserConfigurationException, SAXException {
789
790
791 String file = readFullyToString(inputStream);
792
793
794 file = file.replaceAll("<\\?xml [ a-zA-Z0-9=\".-]*\\?>", "");
795 file = file.replaceAll(
796 "xmlns=\"" + RuleSetWriter.RULESET_NS_URI + "\"", "");
797 file = file.replaceAll(
798 "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"", "");
799 file = file
800 .replaceAll(
801 "xsi:schemaLocation=\"" + RuleSetWriter.RULESET_NS_URI + " http://pmd.sourceforge.net/ruleset_2_0_0.xsd\"",
802 "");
803
804 file = "<?xml version=\"1.0\"?>" + PMD.EOL
805 + "<!DOCTYPE ruleset SYSTEM \"file://"
806 + System.getProperty("user.dir") + "/src/main/resources/ruleset_2_0_0.dtd\">"
807 + PMD.EOL + file;
808
809 inputStream = new ByteArrayInputStream(file.getBytes());
810
811 saxParser.parse(inputStream, validateDefaultHandlerDtd.resetValid());
812 inputStream.close();
813 return validateDefaultHandlerDtd.isValid();
814 }
815
816 private String readFullyToString(InputStream inputStream)
817 throws IOException {
818 StringBuilder buf = new StringBuilder(64 * 1024);
819 BufferedReader reader = new BufferedReader(new InputStreamReader(
820 inputStream));
821 String line;
822 while ((line = reader.readLine()) != null) {
823 buf.append(line);
824 buf.append(PMD.EOL);
825 }
826 reader.close();
827 return buf.toString();
828 }
829
830
831 private List<String> getRuleSetFileNames() throws IOException,
832 RuleSetNotFoundException {
833 Properties properties = new Properties();
834 properties.load(ResourceLoader
835 .loadResourceAsStream("rulesets/java/rulesets.properties"));
836 String fileNames = properties.getProperty("rulesets.filenames");
837 StringTokenizer st = new StringTokenizer(fileNames, ",");
838 List<String> ruleSetFileNames = new ArrayList<String>();
839 while (st.hasMoreTokens()) {
840 ruleSetFileNames.add(st.nextToken());
841 }
842 return ruleSetFileNames;
843 }
844
845 private static class ValidateDefaultHandler extends DefaultHandler {
846 private final String validateDocument;
847 private boolean valid = true;
848
849 public ValidateDefaultHandler(String validateDocument) {
850 this.validateDocument = validateDocument;
851 }
852
853 public ValidateDefaultHandler resetValid() {
854 valid = true;
855 return this;
856 }
857
858 public boolean isValid() {
859 return valid;
860 }
861
862 @Override
863 public void error(SAXParseException e) throws SAXException {
864 log("Error", e);
865 }
866
867 @Override
868 public void fatalError(SAXParseException e) throws SAXException {
869 log("FatalError", e);
870 }
871
872 @Override
873 public void warning(SAXParseException e) throws SAXException {
874 log("Warning", e);
875 }
876
877 private void log(String prefix, SAXParseException e) {
878 String message = prefix + " at (" + e.getLineNumber() + ", " + e.getColumnNumber() + "): " + e.getMessage();
879 System.err.println(message);
880 valid = false;
881 }
882
883 @Override
884 public InputSource resolveEntity(String publicId, String systemId)
885 throws IOException, SAXException {
886 if ("http://pmd.sourceforge.net/ruleset_2_0_0.xsd".equals(systemId)
887 || systemId.endsWith("ruleset_2_0_0.dtd")) {
888 try {
889 InputStream inputStream = loadResourceAsStream(validateDocument);
890 return new InputSource(inputStream);
891 } catch (RuleSetNotFoundException e) {
892 System.err.println(e.getMessage());
893 throw new IOException(e.getMessage());
894 }
895 }
896 throw new IllegalArgumentException(
897 "No clue how to handle: publicId=" + publicId
898 + ", systemId=" + systemId);
899 }
900 }
901
902 private static InputStream loadResourceAsStream(String resource)
903 throws RuleSetNotFoundException {
904 InputStream inputStream = ResourceLoader.loadResourceAsStream(resource,
905 RuleSetFactoryTest.class.getClassLoader());
906 if (inputStream == null) {
907 throw new RuleSetNotFoundException(
908 "Can't find resource "
909 + resource
910 + " Make sure the resource is a valid file or URL or is on the CLASSPATH. Here's the current classpath: "
911 + System.getProperty("java.class.path"));
912 }
913 return inputStream;
914 }
915
916 private static final String REF_OVERRIDE_ORIGINAL_NAME = "<?xml version=\"1.0\"?>"
917 + PMD.EOL
918 + "<ruleset name=\"test\">"
919 + PMD.EOL
920 + " <description>testdesc</description>"
921 + PMD.EOL
922 + " <rule "
923 + PMD.EOL
924 + " ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" message=\"TestMessageOverride\"> "
925 + PMD.EOL + " </rule>" + PMD.EOL + "</ruleset>";
926
927 private static final String REF_MISPELLED_XREF = "<?xml version=\"1.0\"?>"
928 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
929 + " <description>testdesc</description>" + PMD.EOL + " <rule "
930 + PMD.EOL
931 + " ref=\"rulesets/java/unusedcode.xml/FooUnusedLocalVariable\"> "
932 + PMD.EOL + " </rule>" + PMD.EOL + "</ruleset>";
933
934 private static final String REF_OVERRIDE_ORIGINAL_NAME_ONE_ELEM = "<?xml version=\"1.0\"?>"
935 + PMD.EOL
936 + "<ruleset name=\"test\">"
937 + PMD.EOL
938 + " <description>testdesc</description>"
939 + PMD.EOL
940 + " <rule ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" message=\"TestMessageOverride\"/> "
941 + PMD.EOL + "</ruleset>";
942
943 private static final String REF_OVERRIDE = "<?xml version=\"1.0\"?>"
944 + PMD.EOL
945 + "<ruleset name=\"test\">"
946 + PMD.EOL
947 + " <description>testdesc</description>"
948 + PMD.EOL
949 + " <rule "
950 + PMD.EOL
951 + " ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\" "
952 + PMD.EOL
953 + " name=\"TestNameOverride\" "
954 + PMD.EOL
955 + " message=\"Test message override\"> "
956 + PMD.EOL
957 + " <description>Test description override</description>"
958 + PMD.EOL
959 + " <example>Test example override</example>"
960 + PMD.EOL
961 + " <priority>3</priority>"
962 + PMD.EOL
963 + " <properties>"
964 + PMD.EOL
965 + " <property name=\"test2\" description=\"test2\" type=\"String\" value=\"override2\"/>"
966 + PMD.EOL
967 + " <property name=\"test3\" description=\"test3\" type=\"String\"><value>override3</value></property>"
968 + PMD.EOL
969 + " <property name=\"test4\" description=\"test4\" type=\"String\" value=\"new property\"/>"
970 + PMD.EOL + " </properties>" + PMD.EOL + " </rule>" + PMD.EOL
971 + "</ruleset>";
972
973 private static final String REF_INTERNAL_TO_INTERNAL = "<?xml version=\"1.0\"?>"
974 + PMD.EOL
975 + "<ruleset name=\"test\">"
976 + PMD.EOL
977 + " <description>testdesc</description>"
978 + PMD.EOL
979 + "<rule "
980 + PMD.EOL
981 + "name=\"MockRuleName\" "
982 + PMD.EOL
983 + "message=\"avoid the mock rule\" "
984 + PMD.EOL
985 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
986 + PMD.EOL
987 + "</rule>"
988 + " <rule ref=\"MockRuleName\" name=\"MockRuleNameRef\"/> "
989 + PMD.EOL + "</ruleset>";
990
991 private static final String REF_INTERNAL_TO_INTERNAL_CHAIN = "<?xml version=\"1.0\"?>"
992 + PMD.EOL
993 + "<ruleset name=\"test\">"
994 + PMD.EOL
995 + " <description>testdesc</description>"
996 + PMD.EOL
997 + "<rule "
998 + PMD.EOL
999 + "name=\"MockRuleName\" "
1000 + PMD.EOL
1001 + "message=\"avoid the mock rule\" "
1002 + PMD.EOL
1003 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1004 + PMD.EOL
1005 + "</rule>"
1006 + " <rule ref=\"MockRuleName\" name=\"MockRuleNameRef\"><priority>2</priority></rule> "
1007 + PMD.EOL
1008 + " <rule ref=\"MockRuleNameRef\" name=\"MockRuleNameRefRef\"><priority>1</priority></rule> "
1009 + PMD.EOL + "</ruleset>";
1010
1011 private static final String REF_INTERNAL_TO_EXTERNAL = "<?xml version=\"1.0\"?>"
1012 + PMD.EOL
1013 + "<ruleset name=\"test\">"
1014 + PMD.EOL
1015 + " <description>testdesc</description>"
1016 + PMD.EOL
1017 + "<rule "
1018 + PMD.EOL
1019 + "name=\"ExternalRefRuleName\" "
1020 + PMD.EOL
1021 + "ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1022 + PMD.EOL
1023 + " <rule ref=\"ExternalRefRuleName\" name=\"ExternalRefRuleNameRef\"/> "
1024 + PMD.EOL + "</ruleset>";
1025
1026 private static final String REF_INTERNAL_TO_EXTERNAL_CHAIN = "<?xml version=\"1.0\"?>"
1027 + PMD.EOL
1028 + "<ruleset name=\"test\">"
1029 + PMD.EOL
1030 + " <description>testdesc</description>"
1031 + PMD.EOL
1032 + "<rule "
1033 + PMD.EOL
1034 + "name=\"ExternalRefRuleName\" "
1035 + PMD.EOL
1036 + "ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1037 + PMD.EOL
1038 + " <rule ref=\"ExternalRefRuleName\" name=\"ExternalRefRuleNameRef\"><priority>2</priority></rule> "
1039 + PMD.EOL
1040 + " <rule ref=\"ExternalRefRuleNameRef\" name=\"ExternalRefRuleNameRefRef\"><priority>1</priority></rule> "
1041 + PMD.EOL + "</ruleset>";
1042
1043 private static final String EMPTY_RULESET = "<?xml version=\"1.0\"?>"
1044 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1045 + "<description>testdesc</description>" + PMD.EOL + "</ruleset>";
1046
1047 private static final String SINGLE_RULE = "<?xml version=\"1.0\"?>"
1048 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1049 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1050 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1051 + "message=\"avoid the mock rule\" " + PMD.EOL
1052 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1053 + "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1054
1055 private static final String MULTIPLE_RULES = "<?xml version=\"1.0\"?>"
1056 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1057 + "<description>testdesc</description>" + PMD.EOL
1058 + "<rule name=\"MockRuleName1\" " + PMD.EOL
1059 + "message=\"avoid the mock rule\" " + PMD.EOL
1060 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">" + PMD.EOL
1061 + "</rule>" + PMD.EOL + "<rule name=\"MockRuleName2\" " + PMD.EOL
1062 + "message=\"avoid the mock rule\" " + PMD.EOL
1063 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">" + PMD.EOL
1064 + "</rule></ruleset>";
1065
1066 private static final String PROPERTIES = "<?xml version=\"1.0\"?>"
1067 + PMD.EOL
1068 + "<ruleset name=\"test\">"
1069 + PMD.EOL
1070 + "<description>testdesc</description>"
1071 + PMD.EOL
1072 + "<rule name=\"MockRuleName\" "
1073 + PMD.EOL
1074 + "message=\"avoid the mock rule\" "
1075 + PMD.EOL
1076 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1077 + PMD.EOL
1078 + "<description>testdesc2</description>"
1079 + PMD.EOL
1080 + "<properties>"
1081 + PMD.EOL
1082 + "<property name=\"fooBoolean\" description=\"test\" type=\"Boolean\" value=\"true\" />"
1083 + PMD.EOL
1084 + "<property name=\"fooChar\" description=\"test\" type=\"Character\" value=\"B\" />"
1085 + PMD.EOL
1086 + "<property name=\"fooInt\" description=\"test\" type=\"Integer\" min=\"1\" max=\"10\" value=\"3\" />"
1087 + PMD.EOL
1088 + "<property name=\"fooFloat\" description=\"test\" type=\"Float\" min=\"1.0\" max=\"1.0\" value=\"1.0\" />"
1089 + PMD.EOL
1090 + "<property name=\"fooDouble\" description=\"test\" type=\"Double\" min=\"1.0\" max=\"9.0\" value=\"3.0\" />"
1091 + PMD.EOL
1092 + "<property name=\"fooString\" description=\"test\" type=\"String\" value=\"bar\" />"
1093 + PMD.EOL + "</properties>" + PMD.EOL + "</rule></ruleset>";
1094
1095 private static final String XPATH = "<?xml version=\"1.0\"?>" + PMD.EOL
1096 + "<ruleset name=\"test\">" + PMD.EOL
1097 + "<description>testdesc</description>" + PMD.EOL
1098 + "<rule name=\"MockRuleName\" " + PMD.EOL
1099 + "message=\"avoid the mock rule\" " + PMD.EOL
1100 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1101 + "<priority>3</priority>" + PMD.EOL + PMD.EOL
1102 + "<description>testdesc2</description>" + PMD.EOL + "<properties>"
1103 + PMD.EOL
1104 + "<property name=\"xpath\" description=\"test\" type=\"String\">"
1105 + PMD.EOL + "<value>" + PMD.EOL + "<![CDATA[ //Block ]]>" + PMD.EOL
1106 + "</value>" + PMD.EOL + "</property>" + PMD.EOL + "</properties>"
1107 + PMD.EOL + "</rule></ruleset>";
1108
1109 private static final String PRIORITY = "<?xml version=\"1.0\"?>" + PMD.EOL
1110 + "<ruleset name=\"test\">" + PMD.EOL
1111 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1112 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1113 + "message=\"avoid the mock rule\" " + PMD.EOL
1114 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1115 + "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1116
1117 private static final String LANGUAGE = "<?xml version=\"1.0\"?>"
1118 + PMD.EOL
1119 + "<ruleset name=\"test\">"
1120 + PMD.EOL
1121 + "<description>testdesc</description>"
1122 + PMD.EOL
1123 + "<rule "
1124 + PMD.EOL
1125 + "name=\"MockRuleName\" "
1126 + PMD.EOL
1127 + "message=\"avoid the mock rule\" "
1128 + PMD.EOL
1129 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\" language=\"java\">"
1130 + PMD.EOL + "</rule></ruleset>";
1131
1132 private static final String INCORRECT_LANGUAGE = "<?xml version=\"1.0\"?>"
1133 + PMD.EOL + "<ruleset name=\"test\">" + PMD.EOL
1134 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1135 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1136 + "message=\"avoid the mock rule\" " + PMD.EOL
1137 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\"" + PMD.EOL
1138 + " language=\"bogus\">" + PMD.EOL + "</rule></ruleset>";
1139
1140 private static final String MINIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1141 + PMD.EOL
1142 + "<ruleset name=\"test\">"
1143 + PMD.EOL
1144 + "<description>testdesc</description>"
1145 + PMD.EOL
1146 + "<rule "
1147 + PMD.EOL
1148 + "name=\"MockRuleName\" "
1149 + PMD.EOL
1150 + "message=\"avoid the mock rule\" "
1151 + PMD.EOL
1152 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1153 + PMD.EOL
1154 + " language=\"java\""
1155 + PMD.EOL
1156 + " minimumLanguageVersion=\"1.4\">"
1157 + PMD.EOL
1158 + "</rule></ruleset>";
1159
1160 private static final String INCORRECT_MINIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1161 + PMD.EOL
1162 + "<ruleset name=\"test\">"
1163 + PMD.EOL
1164 + "<description>testdesc</description>"
1165 + PMD.EOL
1166 + "<rule "
1167 + PMD.EOL
1168 + "name=\"MockRuleName\" "
1169 + PMD.EOL
1170 + "message=\"avoid the mock rule\" "
1171 + PMD.EOL
1172 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1173 + PMD.EOL
1174 + " language=\"java\""
1175 + PMD.EOL
1176 + " minimumLanguageVersion=\"bogus\">"
1177 + PMD.EOL
1178 + "</rule></ruleset>";
1179
1180 private static final String MAXIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1181 + PMD.EOL
1182 + "<ruleset name=\"test\">"
1183 + PMD.EOL
1184 + "<description>testdesc</description>"
1185 + PMD.EOL
1186 + "<rule "
1187 + PMD.EOL
1188 + "name=\"MockRuleName\" "
1189 + PMD.EOL
1190 + "message=\"avoid the mock rule\" "
1191 + PMD.EOL
1192 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1193 + PMD.EOL
1194 + " language=\"java\""
1195 + PMD.EOL
1196 + " maximumLanguageVersion=\"1.7\">"
1197 + PMD.EOL
1198 + "</rule></ruleset>";
1199
1200 private static final String INCORRECT_MAXIMUM_LANGUAGE_VERSION = "<?xml version=\"1.0\"?>"
1201 + PMD.EOL
1202 + "<ruleset name=\"test\">"
1203 + PMD.EOL
1204 + "<description>testdesc</description>"
1205 + PMD.EOL
1206 + "<rule "
1207 + PMD.EOL
1208 + "name=\"MockRuleName\" "
1209 + PMD.EOL
1210 + "message=\"avoid the mock rule\" "
1211 + PMD.EOL
1212 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\""
1213 + PMD.EOL
1214 + " language=\"java\""
1215 + PMD.EOL
1216 + " maximumLanguageVersion=\"bogus\">"
1217 + PMD.EOL
1218 + "</rule></ruleset>";
1219
1220 private static final String INVERTED_MINIMUM_MAXIMUM_LANGUAGE_VERSIONS = "<?xml version=\"1.0\"?>"
1221 + PMD.EOL
1222 + "<ruleset name=\"test\">"
1223 + PMD.EOL
1224 + "<description>testdesc</description>"
1225 + PMD.EOL
1226 + "<rule "
1227 + PMD.EOL
1228 + "name=\"MockRuleName\" "
1229 + PMD.EOL
1230 + "message=\"avoid the mock rule\" "
1231 + PMD.EOL
1232 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\" "
1233 + PMD.EOL
1234 + "language=\"java\""
1235 + PMD.EOL
1236 + " minimumLanguageVersion=\"1.7\""
1237 + PMD.EOL
1238 + "maximumLanguageVersion=\"1.4\">"
1239 + PMD.EOL
1240 + "</rule></ruleset>";
1241
1242 private static final String DIRECT_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1243 + PMD.EOL
1244 + "<ruleset name=\"test\">"
1245 + PMD.EOL
1246 + "<description>testdesc</description>"
1247 + PMD.EOL
1248 + "<rule "
1249 + PMD.EOL
1250 + "name=\"MockRuleName\" "
1251 + PMD.EOL
1252 + "message=\"avoid the mock rule\" "
1253 + PMD.EOL
1254 + "class=\"net.sourceforge.pmd.lang.rule.MockRule\" deprecated=\"true\">"
1255 + PMD.EOL + "</rule></ruleset>";
1256
1257
1258
1259 private static final String DEPRECATED_RULE_RULESET_NAME = "rulesets/java/basic.xml";
1260
1261
1262
1263 private static final String DEPRECATED_RULE_NAME = "EmptyCatchBlock";
1264
1265 private static final String REFERENCE_TO_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1266 + PMD.EOL
1267 + "<ruleset name=\"test\">"
1268 + PMD.EOL
1269 + "<description>testdesc</description>"
1270 + PMD.EOL
1271 + "<rule "
1272 + PMD.EOL
1273 + "ref=\""
1274 + DEPRECATED_RULE_RULESET_NAME
1275 + "/"
1276 + DEPRECATED_RULE_NAME + "\">" + PMD.EOL + "</rule></ruleset>";
1277
1278 private static final String REFERENCE_TO_RULESET_WITH_DEPRECATED_RULE = "<?xml version=\"1.0\"?>"
1279 + PMD.EOL
1280 + "<ruleset name=\"test\">"
1281 + PMD.EOL
1282 + "<description>testdesc</description>"
1283 + PMD.EOL
1284 + "<rule "
1285 + PMD.EOL
1286 + "ref=\""
1287 + DEPRECATED_RULE_RULESET_NAME
1288 + "\">"
1289 + PMD.EOL + "</rule></ruleset>";
1290
1291 private static final String DFA = "<?xml version=\"1.0\"?>" + PMD.EOL
1292 + "<ruleset name=\"test\">" + PMD.EOL
1293 + "<description>testdesc</description>" + PMD.EOL + "<rule "
1294 + PMD.EOL + "name=\"MockRuleName\" " + PMD.EOL
1295 + "message=\"avoid the mock rule\" " + PMD.EOL + "dfa=\"true\" "
1296 + PMD.EOL + "class=\"net.sourceforge.pmd.lang.rule.MockRule\">"
1297 + "<priority>3</priority>" + PMD.EOL + "</rule></ruleset>";
1298
1299 private static final String INCLUDE_EXCLUDE_RULESET = "<?xml version=\"1.0\"?>"
1300 + PMD.EOL
1301 + "<ruleset name=\"test\">"
1302 + PMD.EOL
1303 + "<description>testdesc</description>"
1304 + PMD.EOL
1305 + "<include-pattern>include1</include-pattern>"
1306 + PMD.EOL
1307 + "<include-pattern>include2</include-pattern>"
1308 + PMD.EOL
1309 + "<exclude-pattern>exclude1</exclude-pattern>"
1310 + PMD.EOL
1311 + "<exclude-pattern>exclude2</exclude-pattern>"
1312 + PMD.EOL
1313 + "<exclude-pattern>exclude3</exclude-pattern>"
1314 + PMD.EOL
1315 + "</ruleset>";
1316
1317 private static final String EXTERNAL_REFERENCE_RULE_SET = "<?xml version=\"1.0\"?>"
1318 + PMD.EOL
1319 + "<ruleset name=\"test\">"
1320 + PMD.EOL
1321 + "<description>testdesc</description>"
1322 + PMD.EOL
1323 + "<rule ref=\"rulesets/java/unusedcode.xml/UnusedLocalVariable\"/>"
1324 + PMD.EOL + "</ruleset>";
1325
1326 private Rule loadFirstRule(String ruleSetXml)
1327 throws RuleSetNotFoundException {
1328 RuleSet rs = loadRuleSet(ruleSetXml);
1329 return rs.getRules().iterator().next();
1330 }
1331
1332 private RuleSet loadRuleSetByFileName(String ruleSetFileName)
1333 throws RuleSetNotFoundException {
1334 RuleSetFactory rsf = new RuleSetFactory();
1335 return rsf.createRuleSet(ruleSetFileName);
1336 }
1337
1338 private RuleSet loadRuleSet(String ruleSetXml)
1339 throws RuleSetNotFoundException {
1340 RuleSetFactory rsf = new RuleSetFactory();
1341 return rsf.createRuleSet(createRuleSetReferenceId(ruleSetXml));
1342 }
1343
1344 private static RuleSetReferenceId createRuleSetReferenceId(
1345 final String ruleSetXml) {
1346 return new RuleSetReferenceId(null) {
1347 @Override
1348 public InputStream getInputStream(ClassLoader classLoader)
1349 throws RuleSetNotFoundException {
1350 return new ByteArrayInputStream(ruleSetXml.getBytes());
1351 }
1352 };
1353 }
1354
1355 public static junit.framework.Test suite() {
1356 return new JUnit4TestAdapter(RuleSetFactoryTest.class);
1357 }
1358
1359 }