diff --git a/pmd-test/pom.xml b/pmd-test/pom.xml index 8e1af3a5da..7484282065 100644 --- a/pmd-test/pom.xml +++ b/pmd-test/pom.xml @@ -27,5 +27,12 @@ org.apache.ant ant-testutil + + + org.mockito + mockito-core + 1.10.19 + test + diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/test/lang/DummyLanguageModule.java b/pmd-test/src/main/java/net/sourceforge/pmd/test/lang/DummyLanguageModule.java new file mode 100644 index 0000000000..3a0fcaa8dc --- /dev/null +++ b/pmd-test/src/main/java/net/sourceforge/pmd/test/lang/DummyLanguageModule.java @@ -0,0 +1,119 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.test.lang; + +import java.io.Reader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.RuleViolation; +import net.sourceforge.pmd.lang.AbstractLanguageVersionHandler; +import net.sourceforge.pmd.lang.AbstractParser; +import net.sourceforge.pmd.lang.BaseLanguageModule; +import net.sourceforge.pmd.lang.Parser; +import net.sourceforge.pmd.lang.ParserOptions; +import net.sourceforge.pmd.lang.TokenManager; +import net.sourceforge.pmd.lang.ast.Node; +import net.sourceforge.pmd.lang.ast.ParseException; +import net.sourceforge.pmd.lang.rule.AbstractRuleChainVisitor; +import net.sourceforge.pmd.lang.rule.AbstractRuleViolationFactory; +import net.sourceforge.pmd.lang.rule.ParametricRuleViolation; +import net.sourceforge.pmd.test.lang.ast.DummyNode; + + +/** + * Dummy language used for testing PMD. + */ +public class DummyLanguageModule extends BaseLanguageModule { + + public static final String NAME = "Dummy"; + public static final String TERSE_NAME = "dummy"; + + public DummyLanguageModule() { + super(NAME, null, TERSE_NAME, DummyRuleChainVisitor.class, "dummy"); + addVersion("1.0", new Handler(), false); + addVersion("1.1", new Handler(), false); + addVersion("1.2", new Handler(), false); + addVersion("1.3", new Handler(), false); + addVersion("1.4", new Handler(), false); + addVersion("1.5", new Handler(), false); + addVersion("1.6", new Handler(), false); + addVersion("1.7", new Handler(), true); + addVersion("1.8", new Handler(), false); + } + + public static class DummyRuleChainVisitor extends AbstractRuleChainVisitor { + @Override + protected void visit(Rule rule, Node node, RuleContext ctx) { + rule.apply(Arrays.asList(node), ctx); + } + @Override + protected void indexNodes(List nodes, RuleContext ctx) { + for (Node n : nodes) { + indexNode(n); + List childs = new ArrayList(); + for (int i = 0; i < n.jjtGetNumChildren(); i++) { + childs.add(n.jjtGetChild(i)); + } + indexNodes(childs, ctx); + } + } + } + + public static class Handler extends AbstractLanguageVersionHandler { + @Override + public RuleViolationFactory getRuleViolationFactory() { + return new RuleViolationFactory(); + } + + @Override + public Parser getParser(ParserOptions parserOptions) { + return new AbstractParser(parserOptions) { + @Override + public Node parse(String fileName, Reader source) throws ParseException { + DummyNode node = new DummyNode(1); + node.testingOnly__setBeginLine(1); + node.testingOnly__setBeginColumn(1); + node.setImage("Foo"); + return node; + } + @Override + public Map getSuppressMap() { + return Collections.emptyMap(); + } + @Override + public boolean canParse() { + return true; + } + @Override + protected TokenManager createTokenManager(Reader source) { + return null; + } + }; + } + } + + public static class RuleViolationFactory extends AbstractRuleViolationFactory { + @Override + protected RuleViolation createRuleViolation(Rule rule, RuleContext ruleContext, Node node, String message) { + return createRuleViolation(rule, ruleContext, node, message, 0, 0); + } + @Override + protected RuleViolation createRuleViolation(Rule rule, RuleContext ruleContext, Node node, String message, + int beginLine, int endLine) { + ParametricRuleViolation rv = new ParametricRuleViolation(rule, ruleContext, node, message) { + { + this.packageName = "foo"; // just for testing variable expansion + } + }; + rv.setLines(beginLine, endLine); + return rv; + } + } +} diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/test/lang/ast/DummyNode.java b/pmd-test/src/main/java/net/sourceforge/pmd/test/lang/ast/DummyNode.java new file mode 100644 index 0000000000..5760c799c6 --- /dev/null +++ b/pmd-test/src/main/java/net/sourceforge/pmd/test/lang/ast/DummyNode.java @@ -0,0 +1,17 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.test.lang.ast; + +import net.sourceforge.pmd.lang.ast.AbstractNode; + +public class DummyNode extends AbstractNode { + public DummyNode(int id) { + super(id); + } + + @Override + public String toString() { + return "dummyNode"; + } +} diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java index 5a83052746..b3a066cfb2 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTst.java @@ -216,7 +216,9 @@ public abstract class RuleTst { ctx.setIgnoreExceptions(false); RuleSet rules = new RuleSet(); rules.addRule(rule); + rules.start(ctx); p.getSourceCodeProcessor().processSourceCode(new StringReader(code), new RuleSets(rules), ctx); + rules.end(ctx); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/pmd-test/src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language b/pmd-test/src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language new file mode 100644 index 0000000000..825247a1cc --- /dev/null +++ b/pmd-test/src/main/resources/META-INF/services/net.sourceforge.pmd.lang.Language @@ -0,0 +1 @@ +net.sourceforge.pmd.test.lang.DummyLanguageModule diff --git a/pmd-test/src/main/resources/rulesets/dummy/basic.xml b/pmd-test/src/main/resources/rulesets/dummy/basic.xml new file mode 100644 index 0000000000..0a141832a2 --- /dev/null +++ b/pmd-test/src/main/resources/rulesets/dummy/basic.xml @@ -0,0 +1,36 @@ + + + + + Ruleset used by test RuleSetReferenceIdTest + + + + +Just for test + + 3 + + + + + + + + + Test + 3 + + + + + + + " + \ No newline at end of file diff --git a/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java new file mode 100644 index 0000000000..0b28df31fa --- /dev/null +++ b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java @@ -0,0 +1,47 @@ +/** + * BSD-style license; for more info see http://pmd.sourceforge.net/license.html + */ +package net.sourceforge.pmd.testframework; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import org.junit.Test; + +import net.sourceforge.pmd.Report; +import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleContext; +import net.sourceforge.pmd.lang.LanguageRegistry; +import net.sourceforge.pmd.lang.LanguageVersion; + +public class RuleTstTest { + + @Test + public void shouldCallStartAndEnd() { + RuleTst ruleTester = new RuleTst() {}; + LanguageVersion languageVersion = LanguageRegistry.findLanguageByTerseName("dummy").getDefaultVersion(); + Report report = new Report(); + Rule rule = mock(Rule.class); + when(rule.getLanguage()).thenReturn(languageVersion.getLanguage()); + when(rule.getName()).thenReturn("test rule"); + + ruleTester.runTestFromString("the code", rule, report, languageVersion, false); + + verify(rule).start(any(RuleContext.class)); + verify(rule).end(any(RuleContext.class)); + verify(rule, times(4)).getLanguage(); + verify(rule).usesDFA(); + verify(rule).usesTypeResolution(); + verify(rule, times(2)).usesRuleChain(); + verify(rule).getMinimumLanguageVersion(); + verify(rule).getMaximumLanguageVersion(); + verify(rule).apply(anyList(), any(RuleContext.class)); + verify(rule).getName(); + verifyNoMoreInteractions(rule); + } +} diff --git a/src/site/markdown/overview/changelog.md b/src/site/markdown/overview/changelog.md index 1af211c370..0a049dab29 100644 --- a/src/site/markdown/overview/changelog.md +++ b/src/site/markdown/overview/changelog.md @@ -19,6 +19,7 @@ * [#1501](https://sourceforge.net/p/pmd/bugs/1501/): \[java] \[apex] CyclomaticComplexity rule causes OOM when class reporting is disabled * General * [#1499](https://sourceforge.net/p/pmd/bugs/1499/): \[core] CPD test break PMD 5.5.1 build on Windows + * [#1506](https://sourceforge.net/p/pmd/bugs/1506/): \[core] When runing any RuleTst, start/end methods not called * [#1508](https://sourceforge.net/p/pmd/bugs/1508/): \[core] \[java] PMD is leaking file handles **API Changes:**