/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.Set;
import org.junit.Test;
import net.sourceforge.pmd.RuleSet.RuleSetBuilder;
import net.sourceforge.pmd.lang.Dummy2LanguageModule;
import net.sourceforge.pmd.lang.DummyLanguageModule;
import net.sourceforge.pmd.lang.LanguageRegistry;
import net.sourceforge.pmd.lang.ast.DummyNode;
import net.sourceforge.pmd.lang.ast.Node;
import net.sourceforge.pmd.lang.rule.MockRule;
import net.sourceforge.pmd.lang.rule.RuleReference;
public class RuleSetTest {
@Test
public void testNoDFA() {
MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
mock.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
RuleSet rs = new RuleSetFactory().createSingleRuleRuleSet(mock);
assertFalse(rs.usesDFA(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)));
}
@Test
public void testIncludesRuleWithDFA() {
MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
mock.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
mock.setUsesDFA();
RuleSet rs = new RuleSetFactory().createSingleRuleRuleSet(mock);
assertTrue(rs.usesDFA(LanguageRegistry.getLanguage(DummyLanguageModule.NAME)));
}
@Test
public void testAccessors() {
RuleSet rs = new RuleSetBuilder(new Random().nextLong())
.withFileName("baz")
.withName("foo")
.withDescription("bar")
.build();
assertEquals("file name mismatch", "baz", rs.getFileName());
assertEquals("name mismatch", "foo", rs.getName());
assertEquals("description mismatch", "bar", rs.getDescription());
}
@Test
public void testGetRuleByName() {
MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
RuleSet rs = new RuleSetFactory().createSingleRuleRuleSet(mock);
assertEquals("unable to fetch rule by name", mock, rs.getRuleByName("name"));
}
@Test
public void testGetRuleByName2() {
MockRule mock = new MockRule("name", "desc", "msg", "rulesetname");
RuleSet rs = new RuleSetFactory().createSingleRuleRuleSet(mock);
assertNull("the rule FooRule must not be found!", rs.getRuleByName("FooRule"));
}
@Test
public void testRuleList() {
MockRule rule = new MockRule("name", "desc", "msg", "rulesetname");
RuleSet ruleset = new RuleSetFactory().createSingleRuleRuleSet(rule);
assertEquals("Size of RuleSet isn't one.", 1, ruleset.size());
Collection<Rule> rules = ruleset.getRules();
Iterator<Rule> i = rules.iterator();
assertTrue("Empty Set", i.hasNext());
assertEquals("Returned set of wrong size.", 1, rules.size());
assertEquals("Rule isn't in ruleset.", rule, i.next());
}
@Test
public void testAddRuleSet() {
RuleSet set1 = new RuleSetBuilder(new Random().nextLong())
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
RuleSet set2 = new RuleSetBuilder(new Random().nextLong())
.addRule(new MockRule("name2", "desc", "msg", "rulesetname"))
.addRuleSet(set1)
.build();
assertEquals("ruleset size wrong", 2, set2.size());
}
@Test(expected = RuntimeException.class)
public void testAddRuleSetByReferenceBad() {
RuleSet set1 = new RuleSetBuilder(new Random().nextLong())
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
RuleSet set2 = new RuleSetBuilder(new Random().nextLong())
.addRule(new MockRule("name2", "desc", "msg", "rulesetname"))
.addRuleSetByReference(set1, false)
.build();
}
@Test
public void testAddRuleSetByReferenceAllRule() {
RuleSet set2 = new RuleSetBuilder(new Random().nextLong())
.withFileName("foo")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.addRule(new MockRule("name2", "desc", "msg", "rulesetname"))
.build();
RuleSet set1 = new RuleSetBuilder(new Random().nextLong())
.addRuleSetByReference(set2, true)
.build();
assertEquals("wrong rule size", 2, set1.getRules().size());
for (Rule rule : set1.getRules()) {
assertTrue("not a rule reference", rule instanceof RuleReference);
RuleReference ruleReference = (RuleReference) rule;
assertEquals("wrong ruleset file name", "foo", ruleReference.getRuleSetReference().getRuleSetFileName());
assertTrue("not all rule reference", ruleReference.getRuleSetReference().isAllRules());
}
}
@Test
public void testAddRuleSetByReferenceSingleRule() {
RuleSet set2 = new RuleSetBuilder(new Random().nextLong())
.withFileName("foo")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.addRule(new MockRule("name2", "desc", "msg", "rulesetname"))
.build();
RuleSet set1 = new RuleSetBuilder(new Random().nextLong())
.addRuleSetByReference(set2, false)
.build();
assertEquals("wrong rule size", 2, set1.getRules().size());
for (Rule rule : set1.getRules()) {
assertTrue("not a rule reference", rule instanceof RuleReference);
RuleReference ruleReference = (RuleReference) rule;
assertEquals("wrong ruleset file name", "foo", ruleReference.getRuleSetReference().getRuleSetFileName());
assertFalse("should not be all rule reference", ruleReference.getRuleSetReference().isAllRules());
}
}
@Test
public void testApply0Rules() throws Exception {
RuleSet ruleset = new RuleSetBuilder(new Random().nextLong()).build();
verifyRuleSet(ruleset, 0, new HashSet<RuleViolation>());
}
@Test
public void testEquals1() {
RuleSet s = new RuleSetBuilder(new Random().nextLong()).build();
assertFalse("A ruleset cannot be equals to null", s.equals(null));
}
@Test
@SuppressWarnings("PMD.UseAssertEqualsInsteadOfAssertTrue")
public void testEquals2() {
RuleSet s = new RuleSetBuilder(new Random().nextLong()).build();
assertTrue("A rulset must be equals to itself", s.equals(s));
}
@Test
public void testEquals3() {
RuleSet s = new RuleSetBuilder(new Random().nextLong())
.withName("basic rules")
.build();
assertFalse("A ruleset cannot be equals to another kind of object", s.equals("basic rules"));
}
@Test
public void testEquals4() {
RuleSet s1 = new RuleSetBuilder(new Random().nextLong())
.withName("my ruleset")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
RuleSet s2 = new RuleSetBuilder(new Random().nextLong())
.withName("my ruleset")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
assertEquals("2 rulesets with same name and rules must be equals", s1, s2);
assertEquals("Equals rulesets must have the same hashcode", s1.hashCode(), s2.hashCode());
}
@Test
public void testEquals5() {
RuleSet s1 = new RuleSetBuilder(new Random().nextLong())
.withName("my ruleset")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
RuleSet s2 = new RuleSetBuilder(new Random().nextLong())
.withName("my other ruleset")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
assertFalse("2 rulesets with different name but same rules must not be equals", s1.equals(s2));
}
@Test
public void testEquals6() {
RuleSet s1 = new RuleSetBuilder(new Random().nextLong())
.withName("my ruleset")
.addRule(new MockRule("name", "desc", "msg", "rulesetname"))
.build();
RuleSet s2 = new RuleSetBuilder(new Random().nextLong())
.withName("my ruleset")
.addRule(new MockRule("other rule", "desc", "msg", "rulesetname"))
.build();
assertFalse("2 rulesets with same name but different rules must not be equals", s1.equals(s2));
}
@Test
public void testLanguageApplies() {
Rule rule = new MockRule();
rule.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
assertFalse("Different languages should not apply",
RuleSet.applies(rule, LanguageRegistry.getLanguage(Dummy2LanguageModule.NAME).getDefaultVersion()));
rule.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
assertTrue("Same language with no min/max should apply",
RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5")));
rule.setMinimumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5"));
assertTrue("Same language with valid min only should apply",
RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5")));
rule.setMaximumLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.6"));
assertTrue("Same language with valid min and max should apply",
RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.5")));
assertFalse("Same language with outside range of min/max should not apply",
RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.4")));
assertFalse("Same language with outside range of min/max should not apply",
RuleSet.applies(rule, LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getVersion("1.7")));
}
@Test
public void testAddExcludePattern() {
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("*")
.build();
assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
assertEquals("Invalid number of patterns", 1, ruleSet.getExcludePatterns().size());
RuleSet ruleSet2 = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("*")
.addExcludePattern("*") // try to create a duplicate
.build();
assertEquals("Invalid number of patterns", 1, ruleSet2.getExcludePatterns().size());
assertEquals("Exclude pattern", "*", ruleSet2.getExcludePatterns().get(0));
assertNotNull("Include patterns", ruleSet2.getIncludePatterns());
assertEquals("Invalid number of include patterns", 0, ruleSet2.getIncludePatterns().size());
}
@Test
public void testAddExcludePatterns() {
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("*")
.addExcludePattern(".*")
.build();
RuleSet ruleSet2 = new RuleSetBuilder(new Random().nextLong())
.addExcludePatterns(ruleSet.getExcludePatterns())
.build();
assertNotNull("Exclude patterns", ruleSet2.getExcludePatterns());
assertEquals("Invalid number of patterns", 2, ruleSet2.getExcludePatterns().size());
RuleSet ruleSet3 = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("*")
.addExcludePattern(".*")
.addExcludePattern(".*") // try to create a duplicate
.build();
assertEquals("Invalid number of patterns", 2, ruleSet3.getExcludePatterns().size());
assertEquals("Exclude pattern", "*", ruleSet3.getExcludePatterns().get(0));
assertEquals("Exclude pattern", ".*", ruleSet3.getExcludePatterns().get(1));
assertNotNull("Include patterns", ruleSet3.getIncludePatterns());
assertEquals("Invalid number of include patterns", 0, ruleSet3.getIncludePatterns().size());
}
@Test
public void testSetExcludePatterns() {
List<String> excludePatterns = new ArrayList<>();
excludePatterns.add("*");
excludePatterns.add(".*");
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong())
.setExcludePatterns(excludePatterns)
.build();
assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
assertEquals("Invalid number of exclude patterns", 2, ruleSet.getExcludePatterns().size());
assertEquals("Exclude pattern", "*", ruleSet.getExcludePatterns().get(0));
assertEquals("Exclude pattern", ".*", ruleSet.getExcludePatterns().get(1));
assertNotNull("Include patterns", ruleSet.getIncludePatterns());
assertEquals("Invalid number of include patterns", 0, ruleSet.getIncludePatterns().size());
}
@Test
public void testAddIncludePattern() {
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong())
.addIncludePattern("*")
.build();
assertNotNull("Include patterns", ruleSet.getIncludePatterns());
assertEquals("Invalid number of patterns", 1, ruleSet.getIncludePatterns().size());
assertEquals("Include pattern", "*", ruleSet.getIncludePatterns().get(0));
assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
assertEquals("Invalid number of exclude patterns", 0, ruleSet.getExcludePatterns().size());
}
@Test
public void testAddIncludePatterns() {
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong())
.addIncludePattern("*")
.addIncludePattern(".*")
.build();
RuleSet ruleSet2 = new RuleSetBuilder(new Random().nextLong())
.addIncludePatterns(ruleSet.getIncludePatterns())
.build();
assertNotNull("Include patterns", ruleSet2.getIncludePatterns());
assertEquals("Invalid number of patterns", 2, ruleSet2.getIncludePatterns().size());
assertEquals("Include pattern", "*", ruleSet2.getIncludePatterns().get(0));
assertEquals("Include pattern", ".*", ruleSet2.getIncludePatterns().get(1));
assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
assertEquals("Invalid number of exclude patterns", 0, ruleSet.getExcludePatterns().size());
}
@Test
public void testSetIncludePatterns() {
List<String> includePatterns = new ArrayList<>();
includePatterns.add("*");
includePatterns.add(".*");
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong())
.setIncludePatterns(includePatterns)
.build();
assertNotNull("Include patterns", ruleSet.getIncludePatterns());
assertEquals("Invalid number of include patterns", 2, ruleSet.getIncludePatterns().size());
assertEquals("Include pattern", "*", ruleSet.getIncludePatterns().get(0));
assertEquals("Include pattern", ".*", ruleSet.getIncludePatterns().get(1));
assertNotNull("Exclude patterns", ruleSet.getExcludePatterns());
assertEquals("Invalid number of exclude patterns", 0, ruleSet.getExcludePatterns().size());
}
@Test
public void testIncludeExcludeApplies() {
File file = new File("C:\\myworkspace\\project\\some\\random\\package\\RandomClass.java");
RuleSet ruleSet = new RuleSetBuilder(new Random().nextLong()).build();
assertTrue("No patterns", ruleSet.applies(file));
ruleSet = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("nomatch")
.build();
assertTrue("Non-matching exclude", ruleSet.applies(file));
ruleSet = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("nomatch")
.addExcludePattern(".*/package/.*")
.build();
assertFalse("Matching exclude", ruleSet.applies(file));
ruleSet = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("nomatch")
.addExcludePattern(".*/package/.*")
.addIncludePattern(".*/randomX/.*")
.build();
assertFalse("Non-matching include", ruleSet.applies(file));
ruleSet = new RuleSetBuilder(new Random().nextLong())
.addExcludePattern("nomatch")
.addExcludePattern(".*/package/.*")
.addIncludePattern(".*/randomX/.*")
.addIncludePattern(".*/random/.*")
.build();
assertTrue("Matching include", ruleSet.applies(file));
}
@Test
public void testIncludeExcludeMultipleRuleSetWithRuleChainApplies() throws PMDException {
File file = new File("C:\\myworkspace\\project\\some\\random\\package\\RandomClass.java");
Rule rule = new FooRule();
rule.setName("FooRule1");
rule.setLanguage(LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
rule.addRuleChainVisit("dummyNode");
assertTrue("RuleChain rule", rule.usesRuleChain());
RuleSet ruleSet1 = new RuleSetBuilder(new Random().nextLong())
.withName("RuleSet1")
.addRule(rule)
.build();
RuleSet ruleSet2 = new RuleSetBuilder(new Random().nextLong())
.withName("RuleSet2")
.addRule(rule)
.build();
RuleSets ruleSets = new RuleSets();
ruleSets.addRuleSet(ruleSet1);
ruleSets.addRuleSet(ruleSet2);
// Two violations
PMD p = new PMD();
RuleContext ctx = new RuleContext();
Report r = new Report();
ctx.setReport(r);
ctx.setSourceCodeFilename(file.getName());
ctx.setSourceCodeFile(file);
ctx.setLanguageVersion(LanguageRegistry.getLanguage(DummyLanguageModule.NAME).getDefaultVersion());
ruleSets.apply(makeCompilationUnits(), ctx, LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
assertEquals("Violations", 2, r.size());
// One violation
ruleSet1 = new RuleSetBuilder(new Random().nextLong())
.withName("RuleSet1")
.addExcludePattern(".*/package/.*")
.addRule(rule)
.build();
ruleSets = new RuleSets();
ruleSets.addRuleSet(ruleSet1);
ruleSets.addRuleSet(ruleSet2);
r = new Report();
ctx.setReport(r);
ruleSets.apply(makeCompilationUnits(), ctx, LanguageRegistry.getLanguage(DummyLanguageModule.NAME));
assertEquals("Violations", 1, r.size());
}
private void verifyRuleSet(RuleSet ruleset, int size, Set<RuleViolation> values) {
RuleContext context = new RuleContext();
Set<RuleViolation> reportedValues = new HashSet<>();
context.setReport(new Report());
ruleset.apply(makeCompilationUnits(), context);
assertEquals("Invalid number of Violations Reported", size, context.getReport().size());
Iterator<RuleViolation> violations = context.getReport().iterator();
while (violations.hasNext()) {
RuleViolation violation = violations.next();
reportedValues.add(violation);
assertTrue("Unexpected Violation Returned: " + violation, values.contains(violation));
}
Iterator<RuleViolation> expected = values.iterator();
while (expected.hasNext()) {
RuleViolation violation = expected.next();
assertTrue("Expected Violation not Returned: " + violation, reportedValues.contains(violation));
}
}
private List<Node> makeCompilationUnits() {
List<Node> nodes = new ArrayList<>();
DummyNode node = new DummyNode(1);
node.testingOnlySetBeginLine(1);
node.testingOnlySetBeginColumn(1);
node.setImage("Foo");
nodes.add(node);
return nodes;
}
}