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