View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
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.assertNull;
10  import static org.junit.Assert.assertTrue;
11  
12  import java.io.File;
13  import java.util.ArrayList;
14  import java.util.Collection;
15  import java.util.HashSet;
16  import java.util.Iterator;
17  import java.util.List;
18  import java.util.Set;
19  
20  import net.sourceforge.pmd.lang.Dummy2LanguageModule;
21  import net.sourceforge.pmd.lang.DummyLanguageModule;
22  import net.sourceforge.pmd.lang.LanguageRegistry;
23  import net.sourceforge.pmd.lang.ast.DummyNode;
24  import net.sourceforge.pmd.lang.ast.Node;
25  import net.sourceforge.pmd.lang.rule.MockRule;
26  import net.sourceforge.pmd.lang.rule.RuleReference;
27  
28  import org.junit.Test;
29  
30  
31  public class RuleSetTest {
32  
33      private String javaCode = "public class Test { }";
34  
35      @Test
36      public void testNoDFA() {
37  	RuleSet rs = new RuleSet();
38  	MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
39      mock.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
40  	rs.addRule(mock);
41  	assertFalse(rs.usesDFA(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)));
42      }
43  
44      @Test
45      public void testIncludesRuleWithDFA() {
46  	RuleSet rs = new RuleSet();
47  	MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
48  	mock.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
49  	mock.setUsesDFA();
50  	rs.addRule(mock);
51  	assertTrue(rs.usesDFA(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)));
52      }
53  
54      @Test
55      public void testAccessors() {
56  	RuleSet rs = new RuleSet();
57  	rs.setFileName("baz");
58  	assertEquals("file name mismatch", "baz", rs.getFileName());
59  	rs.setName("foo");
60  	assertEquals("name mismatch", "foo", rs.getName());
61  	rs.setDescription("bar");
62  	assertEquals("description mismatch", "bar", rs.getDescription());
63      }
64  
65      @Test
66      public void testGetRuleByName() {
67  	RuleSet rs = new RuleSet();
68  	MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
69  	rs.addRule(mock);
70  	assertEquals("unable to fetch rule by name", mock, rs.getRuleByName("name"));
71      }
72  
73      @Test
74      public void testGetRuleByName2() {
75  	RuleSet rs = new RuleSet();
76  	MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
77  	rs.addRule(mock);
78  	assertNull("the rule FooRule must not be found!", rs.getRuleByName("FooRule"));
79      }
80  
81      @Test
82      public void testRuleList() {
83  	RuleSet IUT = new RuleSet();
84  
85  	assertEquals("Size of RuleSet isn't zero.", 0, IUT.size());
86  
87  	MockRule rule = new MockRule("name", "desc", "msg", "rulesetname");
88  	IUT.addRule(rule);
89  
90  	assertEquals("Size of RuleSet isn't one.", 1, IUT.size());
91  
92  	Collection rules = IUT.getRules();
93  
94  	Iterator i = rules.iterator();
95  	assertTrue("Empty Set", i.hasNext());
96  	assertEquals("Returned set of wrong size.", 1, rules.size());
97  	assertEquals("Rule isn't in ruleset.", rule, i.next());
98      }
99  
100     @Test
101     public void testAddRuleSet() {
102 	RuleSet set1 = new RuleSet();
103 	set1.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
104 	RuleSet set2 = new RuleSet();
105 	set2.addRule(new MockRule("name2", "desc", "msg", "rulesetname"));
106 	set1.addRuleSet(set2);
107 	assertEquals("ruleset size wrong", 2, set1.size());
108     }
109 
110     @Test(expected = RuntimeException.class)
111     public void testAddRuleSetByReferenceBad() {
112 	RuleSet set1 = new RuleSet();
113 	set1.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
114 	RuleSet set2 = new RuleSet();
115 	set2.addRule(new MockRule("name2", "desc", "msg", "rulesetname"));
116 	set1.addRuleSetByReference(set2, false);
117     }
118 
119     @Test
120     public void testAddRuleSetByReferenceAllRule() {
121 	RuleSet set1 = new RuleSet();
122 	RuleSet set2 = new RuleSet();
123 	set2.setFileName("foo");
124 	set2.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
125 	set2.addRule(new MockRule("name2", "desc", "msg", "rulesetname"));
126 	set1.addRuleSetByReference(set2, true);
127 	assertEquals("wrong rule size", 2, set1.getRules().size());
128 	for (Rule rule : set1.getRules()) {
129 	    assertTrue("not a rule reference", rule instanceof RuleReference);
130 	    RuleReference ruleReference = (RuleReference) rule;
131 	    assertEquals("wrong ruleset file name", "foo", ruleReference.getRuleSetReference().getRuleSetFileName());
132 	    assertTrue("not all rule reference", ruleReference.getRuleSetReference().isAllRules());
133 	}
134     }
135 
136     @Test
137     public void testAddRuleSetByReferenceSingleRule() {
138 	RuleSet set1 = new RuleSet();
139 	RuleSet set2 = new RuleSet();
140 	set2.setFileName("foo");
141 	set2.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
142 	set2.addRule(new MockRule("name2", "desc", "msg", "rulesetname"));
143 	set1.addRuleSetByReference(set2, false);
144 	assertEquals("wrong rule size", 2, set1.getRules().size());
145 	for (Rule rule : set1.getRules()) {
146 	    assertTrue("not a rule reference", rule instanceof RuleReference);
147 	    RuleReference ruleReference = (RuleReference) rule;
148 	    assertEquals("wrong ruleset file name", "foo", ruleReference.getRuleSetReference().getRuleSetFileName());
149 	    assertFalse("should not be all rule reference", ruleReference.getRuleSetReference().isAllRules());
150 	}
151     }
152 
153     @Test
154     public void testApply0Rules() throws Throwable {
155 	RuleSet IUT = new RuleSet();
156 	verifyRuleSet(IUT, 0, new HashSet());
157     }
158 
159     @Test
160     public void testEquals1() {
161 	RuleSet s = new RuleSet();
162 	assertFalse("A ruleset cannot be equals to null", s.equals(null));
163     }
164 
165     @Test
166     @SuppressWarnings("PMD.UseAssertEqualsInsteadOfAssertTrue")
167     public void testEquals2() {
168 	RuleSet s = new RuleSet();
169 	assertTrue("A rulset must be equals to itself", s.equals(s));
170     }
171 
172     @Test
173     public void testEquals3() {
174 	RuleSet s = new RuleSet();
175 	s.setName("basic rules");
176 	assertFalse("A ruleset cannot be equals to another kind of object", s.equals("basic rules"));
177     }
178 
179     @Test
180     public void testEquals4() {
181 	RuleSet s1 = new RuleSet();
182 	s1.setName("my ruleset");
183 	s1.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
184 
185 	RuleSet s2 = new RuleSet();
186 	s2.setName("my ruleset");
187 	s2.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
188 
189 	assertEquals("2 rulesets with same name and rules must be equals", s1, s2);
190 	assertEquals("Equals rulesets must have the same hashcode", s1.hashCode(), s2.hashCode());
191     }
192 
193     @Test
194     public void testEquals5() {
195 	RuleSet s1 = new RuleSet();
196 	s1.setName("my ruleset");
197 	s1.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
198 
199 	RuleSet s2 = new RuleSet();
200 	s2.setName("my other ruleset");
201 	s2.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
202 
203 	assertFalse("2 rulesets with different name but same rules must not be equals", s1.equals(s2));
204     }
205 
206     @Test
207     public void testEquals6() {
208 	RuleSet s1 = new RuleSet();
209 	s1.setName("my ruleset");
210 	s1.addRule(new MockRule("name", "desc", "msg", "rulesetname"));
211 
212 	RuleSet s2 = new RuleSet();
213 	s2.setName("my ruleset");
214 	s2.addRule(new MockRule("other rule", "desc", "msg", "rulesetname"));
215 
216 	assertFalse("2 rulesets with same name but different rules must not be equals", s1.equals(s2));
217     }
218     
219     @Test
220     public void testLanguageApplies() {
221 
222 	Rule rule = new MockRule();
223 
224 	rule.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
225 	assertFalse("Different languages should not apply", RuleSet.applies(rule, LanguageRegistry.getLanguage(Dummy2LanguageModule.NAME).getDefaultVersion()));
226 
227 	rule.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
228 	assertTrue("Same language with no min/max should apply", RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5")));
229 
230 	rule.setMinimumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5"));
231 	assertTrue("Same language with valid min only should apply", RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5")));
232 
233 	rule.setMaximumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.6"));
234 	assertTrue("Same language with valid min and max should apply", RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5")));
235 	assertFalse("Same language with outside range of min/max should not apply", RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.4")));
236 	assertFalse("Same language with outside range of min/max should not apply", RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.7")));
237     }
238 
239     @Test
240     public void testAddExcludePattern() {
241 	RuleSet ruleSet = new RuleSet();
242 	ruleSet.addExcludePattern("*");
243 	assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
244 	assertEquals("Invalid number of patterns", 1, ruleSet.getExcludePatterns().size());
245 	ruleSet.addExcludePattern("*");		// try to create a duplicate
246 	assertEquals("Invalid number of patterns", 1, ruleSet.getExcludePatterns().size());	
247 	assertEquals("Exclude pattern", "*", ruleSet.getExcludePatterns().get(0));
248 	assertNotNull("Include patterns", ruleSet.getIncludePatterns());
249 	assertEquals("Invalid number of include patterns", 0, ruleSet.getIncludePatterns().size());
250     }
251 
252     @Test
253     public void testAddExcludePatterns() {
254 	RuleSet ruleSet = new RuleSet();
255 	ruleSet.addExcludePattern("*");
256 	ruleSet.addExcludePattern(".*");
257 	RuleSet ruleSet2 = new RuleSet();
258 	ruleSet2.addExcludePatterns(ruleSet.getExcludePatterns());
259 	assertNotNull("Exclude patterns", ruleSet2.getExcludePatterns());
260 	assertEquals("Invalid number of patterns", 2, ruleSet2.getExcludePatterns().size());
261 	ruleSet.addExcludePattern(".*");	// try to create a duplicate
262 	assertEquals("Invalid number of patterns", 2, ruleSet2.getExcludePatterns().size());
263 	assertEquals("Exclude pattern", "*", ruleSet2.getExcludePatterns().get(0));
264 	assertEquals("Exclude pattern", ".*", ruleSet2.getExcludePatterns().get(1));
265 	assertNotNull("Include patterns", ruleSet2.getIncludePatterns());
266 	assertEquals("Invalid number of include patterns", 0, ruleSet2.getIncludePatterns().size());
267     }
268 
269     @Test
270     public void testSetExcludePatterns() {
271 	List<String> excludePatterns = new ArrayList<String>();
272 	excludePatterns.add("*");
273 	excludePatterns.add(".*");
274 	RuleSet ruleSet = new RuleSet();
275 	ruleSet.setExcludePatterns(excludePatterns);
276 	assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
277 	assertEquals("Invalid number of exclude patterns", 2, ruleSet.getExcludePatterns().size());
278 	assertEquals("Exclude pattern", "*", ruleSet.getExcludePatterns().get(0));
279 	assertEquals("Exclude pattern", ".*", ruleSet.getExcludePatterns().get(1));
280 	assertNotNull("Include patterns", ruleSet.getIncludePatterns());
281 	assertEquals("Invalid number of include patterns", 0, ruleSet.getIncludePatterns().size());
282     }
283 
284     @Test
285     public void testAddIncludePattern() {
286 	RuleSet ruleSet = new RuleSet();
287 	ruleSet.addIncludePattern("*");
288 	assertNotNull("Include patterns", ruleSet.getIncludePatterns());
289 	assertEquals("Invalid number of patterns", 1, ruleSet.getIncludePatterns().size());
290 	assertEquals("Include pattern", "*", ruleSet.getIncludePatterns().get(0));
291 	assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
292 	assertEquals("Invalid number of exclude patterns", 0, ruleSet.getExcludePatterns().size());
293     }
294 
295     @Test
296     public void testAddIncludePatterns() {
297 	RuleSet ruleSet = new RuleSet();
298 	ruleSet.addIncludePattern("*");
299 	ruleSet.addIncludePattern(".*");
300 	RuleSet ruleSet2 = new RuleSet();
301 	ruleSet2.addIncludePatterns(ruleSet.getIncludePatterns());
302 	assertNotNull("Include patterns", ruleSet2.getIncludePatterns());
303 	assertEquals("Invalid number of patterns", 2, ruleSet2.getIncludePatterns().size());
304 	assertEquals("Include pattern", "*", ruleSet2.getIncludePatterns().get(0));
305 	assertEquals("Include pattern", ".*", ruleSet2.getIncludePatterns().get(1));
306 	assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
307 	assertEquals("Invalid number of exclude patterns", 0, ruleSet.getExcludePatterns().size());
308     }
309 
310     @Test
311     public void testSetIncludePatterns() {
312 	List<String> includePatterns = new ArrayList<String>();
313 	includePatterns.add("*");
314 	includePatterns.add(".*");
315 	RuleSet ruleSet = new RuleSet();
316 	ruleSet.setIncludePatterns(includePatterns);
317 	assertNotNull("Include patterns", ruleSet.getIncludePatterns());
318 	assertEquals("Invalid number of include patterns", 2, ruleSet.getIncludePatterns().size());
319 	assertEquals("Include pattern", "*", ruleSet.getIncludePatterns().get(0));
320 	assertEquals("Include pattern", ".*", ruleSet.getIncludePatterns().get(1));
321 	assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
322 	assertEquals("Invalid number of exclude patterns", 0, ruleSet.getExcludePatterns().size());
323     }
324 
325     @Test
326     public void testIncludeExcludeApplies() {
327 	File file = new File("C:\\myworkspace\\project\\some\\random\\package\\RandomClass.java");
328 
329 	RuleSet ruleSet = new RuleSet();
330 	assertTrue("No patterns", ruleSet.applies(file));
331 
332 	ruleSet = new RuleSet();
333 	ruleSet.addExcludePattern("nomatch");
334 	assertTrue("Non-matching exclude", ruleSet.applies(file));
335 
336 	ruleSet = new RuleSet();
337 	ruleSet.addExcludePattern("nomatch");
338 	ruleSet.addExcludePattern(".*/package/.*");
339 	assertFalse("Matching exclude", ruleSet.applies(file));
340 
341 	ruleSet = new RuleSet();
342 	ruleSet.addExcludePattern("nomatch");
343 	ruleSet.addExcludePattern(".*/package/.*");
344 	ruleSet.addIncludePattern(".*/randomX/.*");
345 	assertFalse("Non-matching include", ruleSet.applies(file));
346 
347 	ruleSet = new RuleSet();
348 	ruleSet.addExcludePattern("nomatch");
349 	ruleSet.addExcludePattern(".*/package/.*");
350 	ruleSet.addIncludePattern(".*/randomX/.*");
351 	ruleSet.addIncludePattern(".*/random/.*");
352 	assertTrue("Matching include", ruleSet.applies(file));
353     }
354 
355     @Test
356     public void testIncludeExcludeMultipleRuleSetWithRuleChainApplies() throws PMDException {
357 	File file = new File("C:\\myworkspace\\project\\some\\random\\package\\RandomClass.java");
358 
359 	RuleSet ruleSet1 = new RuleSet();
360 	ruleSet1.setName("RuleSet1");
361 	Rule rule = new FooRule();
362 	rule.setName("FooRule1");
363 	rule.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
364 	rule.addRuleChainVisit("dummyNode");
365 	assertTrue("RuleChain rule", rule.usesRuleChain());
366 	ruleSet1.addRule(rule);
367 
368 	RuleSet ruleSet2 = new RuleSet();
369 	ruleSet2.setName("RuleSet2");
370 	ruleSet2.addRule(rule);
371 
372 	RuleSets ruleSets = new RuleSets();
373 	ruleSets.addRuleSet(ruleSet1);
374 	ruleSets.addRuleSet(ruleSet2);
375 
376 	// Two violations
377         PMD p = new PMD();
378         RuleContext ctx = new RuleContext();
379         Report r = new Report();
380         ctx.setReport(r);
381         ctx.setSourceCodeFilename(file.getName());
382         ctx.setSourceCodeFile(file);
383         ctx.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion());
384         ruleSets.apply(makeCompilationUnits(), ctx, LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
385         assertEquals("Violations", 2, r.size());
386 
387         // One violation
388 	ruleSet1 = new RuleSet();
389 	ruleSet1.setName("RuleSet1");
390         ruleSet1.addExcludePattern(".*/package/.*");
391 	ruleSet1.addRule(rule);
392 
393 	ruleSets = new RuleSets();
394 	ruleSets.addRuleSet(ruleSet1);
395 	ruleSets.addRuleSet(ruleSet2);
396 
397         r = new Report();
398         ctx.setReport(r);
399         ruleSets.apply(makeCompilationUnits(), ctx, LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
400         assertEquals("Violations", 1, r.size());
401     }
402 
403     private void verifyRuleSet(RuleSet IUT, int size, Set values) throws Throwable {
404 
405 	RuleContext context = new RuleContext();
406 	Set<RuleViolation> reportedValues = new HashSet<RuleViolation>();
407 	context.setReport(new Report());
408 	IUT.apply(makeCompilationUnits(), context);
409 
410 	assertEquals("Invalid number of Violations Reported", size, context.getReport().size());
411 
412 	Iterator violations = context.getReport().iterator();
413 	while (violations.hasNext()) {
414 	    RuleViolation violation = (RuleViolation) violations.next();
415 
416 	    reportedValues.add(violation);
417 	    assertTrue("Unexpected Violation Returned: " + violation, values.contains(violation));
418 	}
419 
420 	Iterator expected = values.iterator();
421 	while (expected.hasNext()) {
422 	    RuleViolation violation = (RuleViolation) expected.next();
423 	    assertTrue("Expected Violation not Returned: " + violation, reportedValues.contains(violation));
424 	}
425     }
426 
427     private List<Node> makeCompilationUnits() {
428         List<Node> RC = new ArrayList<Node>();
429         DummyNode node = new DummyNode(1);
430         node.testingOnly__setBeginLine(1);
431         node.testingOnly__setBeginColumn(1);
432         node.setImage("Foo");
433         RC.add(node);
434         return RC;
435     }
436 }