From 4308aafe92ae21b1e2410d83ce4a47f135cb6a63 Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 22 Jul 2022 14:14:12 +0200 Subject: [PATCH 01/10] Update gems Fixes https://github.com/pmd/pmd/security/dependabot/22 TZInfo relative path traversal vulnerability allows loading of arbitrary files CVE-2022-31163 https://github.com/advisories/GHSA-5cm2-9h8c-rvfx --- Gemfile.lock | 28 ++++++++++++------------ docs/Gemfile.lock | 56 +++++++++++++++-------------------------------- 2 files changed, 32 insertions(+), 52 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b41e9645e9..0a16d16858 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -43,11 +43,11 @@ GEM faraday-em_http (1.0.0) faraday-em_synchrony (1.0.0) faraday-excon (1.1.0) - faraday-http-cache (2.2.0) + faraday-http-cache (2.4.0) faraday (>= 0.8) faraday-httpclient (1.0.1) - faraday-multipart (1.0.3) - multipart-post (>= 1.2, < 3) + faraday-multipart (1.0.4) + multipart-post (~> 2) faraday-net_http (1.0.1) faraday-net_http_persistent (1.2.0) faraday-patron (1.0.0) @@ -65,15 +65,15 @@ GEM liquid (5.3.0) logger-colors (1.0.0) mini_portile2 (2.8.0) - multipart-post (2.1.1) + multipart-post (2.2.3) nap (1.1.0) no_proxy_fix (0.1.2) - nokogiri (1.13.6) + nokogiri (1.13.7) mini_portile2 (~> 2.8.0) racc (~> 1.4) - octokit (4.22.0) - faraday (>= 0.9) - sawyer (~> 0.8.0, >= 0.5.3) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) open4 (1.3.4) pmdtester (1.5.1) differ (~> 0.1) @@ -87,20 +87,20 @@ GEM racc (1.6.0) rchardet (1.8.0) rexml (3.2.5) - rouge (3.28.0) + rouge (3.29.0) ruby2_keywords (0.0.5) - rufus-scheduler (3.8.1) + rufus-scheduler (3.8.2) fugit (~> 1.1, >= 1.1.6) safe_yaml (1.0.5) - sawyer (0.8.2) + sawyer (0.9.2) addressable (>= 2.3.5) - faraday (> 0.8, < 2.0) + faraday (>= 0.17.3, < 3) slop (4.9.2) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) - tzinfo (2.0.4) + tzinfo (2.0.5) concurrent-ruby (~> 1.0) - unicode-display_width (2.1.0) + unicode-display_width (2.2.0) PLATFORMS ruby diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index af044ad8d5..f85828b039 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - activesupport (6.0.5) + activesupport (6.0.5.1) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -14,7 +14,7 @@ GEM execjs coffee-script-source (1.11.1) colorator (1.1.0) - commonmarker (0.23.4) + commonmarker (0.23.5) concurrent-ruby (1.1.10) dnsruby (1.61.9) simpleidn (~> 0.1) @@ -25,33 +25,14 @@ GEM ffi (>= 1.15.0) eventmachine (1.2.7) execjs (2.8.1) - faraday (1.10.0) - faraday-em_http (~> 1.0) - faraday-em_synchrony (~> 1.0) - faraday-excon (~> 1.1) - faraday-httpclient (~> 1.0) - faraday-multipart (~> 1.0) - faraday-net_http (~> 1.0) - faraday-net_http_persistent (~> 1.0) - faraday-patron (~> 1.0) - faraday-rack (~> 1.0) - faraday-retry (~> 1.0) + faraday (2.3.0) + faraday-net_http (~> 2.0) ruby2_keywords (>= 0.0.4) - faraday-em_http (1.0.0) - faraday-em_synchrony (1.0.0) - faraday-excon (1.1.0) - faraday-httpclient (1.0.1) - faraday-multipart (1.0.3) - multipart-post (>= 1.2, < 3) - faraday-net_http (1.0.1) - faraday-net_http_persistent (1.2.0) - faraday-patron (1.0.0) - faraday-rack (1.0.0) - faraday-retry (1.0.3) + faraday-net_http (2.0.3) ffi (1.15.5) forwardable-extended (2.6.0) gemoji (3.0.1) - github-pages (226) + github-pages (227) github-pages-health-check (= 1.17.9) jekyll (= 3.9.2) jekyll-avatar (= 0.7.0) @@ -93,7 +74,7 @@ GEM liquid (= 4.0.3) mercenary (~> 0.3) minima (= 2.5.1) - nokogiri (>= 1.13.4, < 2.0) + nokogiri (>= 1.13.6, < 2.0) rouge (= 3.26.0) terminal-table (~> 1.4) github-pages-health-check (1.17.9) @@ -102,7 +83,7 @@ GEM octokit (~> 4.0) public_suffix (>= 3.0, < 5.0) typhoeus (~> 1.3) - html-pipeline (2.14.1) + html-pipeline (2.14.2) activesupport (>= 2) nokogiri (>= 1.4) http_parser.rb (0.8.0) @@ -230,14 +211,13 @@ GEM jekyll (>= 3.5, < 5.0) jekyll-feed (~> 0.9) jekyll-seo-tag (~> 2.1) - minitest (5.15.0) - multipart-post (2.1.1) - nokogiri (1.13.6) + minitest (5.16.2) + nokogiri (1.13.7) mini_portile2 (~> 2.8.0) racc (~> 1.4) - octokit (4.22.0) - faraday (>= 0.9) - sawyer (~> 0.8.0, >= 0.5.3) + octokit (4.25.1) + faraday (>= 1, < 3) + sawyer (~> 0.9) pathutil (0.16.2) forwardable-extended (~> 2.6) public_suffix (4.0.7) @@ -255,9 +235,9 @@ GEM sass-listen (4.0.0) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) - sawyer (0.8.2) + sawyer (0.9.2) addressable (>= 2.3.5) - faraday (> 0.8, < 2.0) + faraday (>= 0.17.3, < 3) simpleidn (0.2.1) unf (~> 0.1.4) terminal-table (1.8.0) @@ -265,13 +245,13 @@ GEM thread_safe (0.3.6) typhoeus (1.4.0) ethon (>= 0.9.0) - tzinfo (1.2.9) + tzinfo (1.2.10) thread_safe (~> 0.1) unf (0.1.4) unf_ext - unf_ext (0.0.8.1) + unf_ext (0.0.8.2) unicode-display_width (1.8.0) - zeitwerk (2.5.4) + zeitwerk (2.6.0) PLATFORMS ruby From 34acac180c58e313a0e3f4e8e22f928e45028326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 22 Jul 2022 14:15:37 +0200 Subject: [PATCH 02/10] Add focused attr to the schema --- .../pmd/test/schema/rule-tests_1_0_0.xsd | 20 ++++++++++++++++++- .../src/main/resources/rule-tests_1_0_0.xsd | 20 ++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd b/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd index 12d39b7976..1a049af0b6 100644 --- a/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd +++ b/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd @@ -58,7 +58,13 @@ - + + + + This attribute is deprecated, it is assumed true and ignored. + + + @@ -76,6 +82,18 @@ + + + + If true, only this test will be executed, and all others will be disabled. + If several tests in the same file are focused, then the last one wins, in + document order. + This attribute is provided as a way for developers to temporarily focus on a single test. + Test files with a focused test should not be checked in. For this reason, + using this attribute produces a warning. + + + diff --git a/pmd-test/src/main/resources/rule-tests_1_0_0.xsd b/pmd-test/src/main/resources/rule-tests_1_0_0.xsd index 12d39b7976..1a049af0b6 100644 --- a/pmd-test/src/main/resources/rule-tests_1_0_0.xsd +++ b/pmd-test/src/main/resources/rule-tests_1_0_0.xsd @@ -58,7 +58,13 @@ - + + + + This attribute is deprecated, it is assumed true and ignored. + + + @@ -76,6 +82,18 @@ + + + + If true, only this test will be executed, and all others will be disabled. + If several tests in the same file are focused, then the last one wins, in + document order. + This attribute is provided as a way for developers to temporarily focus on a single test. + Test files with a focused test should not be checked in. For this reason, + using this attribute produces a warning. + + + From 80659298792b2ba1d29543aea17eb39ff103b06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 22 Jul 2022 14:33:24 +0200 Subject: [PATCH 03/10] Add impl to parse focused attr --- .../pmd/test/schema/BaseTestParserImpl.java | 7 ++++++ .../pmd/test/schema/RuleTestCollection.java | 13 ++++++++++ .../pmd/test/schema/RuleTestDescriptor.java | 9 +++++++ .../pmd/testframework/RuleTestRunner.java | 24 +++++++++---------- .../pmd/testframework/RuleTst.java | 10 ++++++++ .../pmd/testframework/TestDescriptor.java | 2 ++ 6 files changed, 53 insertions(+), 12 deletions(-) diff --git a/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/BaseTestParserImpl.java b/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/BaseTestParserImpl.java index 845625c93e..192b11ba4a 100644 --- a/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/BaseTestParserImpl.java +++ b/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/BaseTestParserImpl.java @@ -100,6 +100,13 @@ class BaseTestParserImpl { descriptor.setDisabled(disabled); + + boolean focused = parseBoolAttribute(testCode, "focused", false, err, + "Attribute focused is used, do not forget to remove it when checking in sources"); + + descriptor.setFocused(focused); + + Properties properties = parseRuleProperties(testCode, descriptor.getRule(), err); descriptor.getProperties().putAll(properties); diff --git a/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestCollection.java b/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestCollection.java index 8ce61f6c70..6ea8172184 100644 --- a/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestCollection.java +++ b/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestCollection.java @@ -28,4 +28,17 @@ public class RuleTestCollection { return Collections.unmodifiableList(tests); } + /** + * Returns the last test of the collection which is focused. + */ + public RuleTestDescriptor getFocusedTestOrNull() { + RuleTestDescriptor focused = null; + for (RuleTestDescriptor test : tests) { + if (test.isFocused()) { + focused = test; + } + } + return focused; + } + } diff --git a/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestDescriptor.java b/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestDescriptor.java index 6d45540b1b..0842709eee 100644 --- a/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestDescriptor.java +++ b/pmd-test-schema/src/main/java/net/sourceforge/pmd/test/schema/RuleTestDescriptor.java @@ -16,6 +16,7 @@ import net.sourceforge.pmd.lang.LanguageVersion; public class RuleTestDescriptor { private boolean disabled; + private boolean focused; private String description; private LanguageVersion languageVersion; private final Properties properties = new Properties(); @@ -106,4 +107,12 @@ public class RuleTestDescriptor { public List getExpectedMessages() { return expectedMessages; } + + public boolean isFocused() { + return focused; + } + + public void setFocused(boolean focused) { + this.focused = focused; + } } diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java index 7007053ffc..7e1e5606db 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java @@ -5,9 +5,7 @@ package net.sourceforge.pmd.testframework; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -26,6 +24,8 @@ import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.test.schema.RuleTestCollection; +import net.sourceforge.pmd.test.schema.RuleTestDescriptor; /** * A JUnit Runner, that executes all declared rule tests in the class. @@ -64,18 +64,18 @@ public class RuleTestRunner extends ParentRunner { @Override protected List getChildren() { List rules = new ArrayList<>(instance.getRules()); - Collections.sort(rules, new Comparator() { - @Override - public int compare(Rule o1, Rule o2) { - return o1.getName().compareTo(o2.getName()); - } - }); + rules.sort(Comparator.comparing(Rule::getName)); - List tests = new LinkedList<>(); + List tests = new ArrayList<>(); for (Rule r : rules) { - TestDescriptor[] ruleTests = instance.extractTestsFromXml(r); - for (TestDescriptor t : ruleTests) { - tests.add(t); + RuleTestCollection ruleTests = instance.parseTestCollection(r); + RuleTestDescriptor focused = ruleTests.getFocusedTestOrNull(); + for (RuleTestDescriptor t : ruleTests.getTests()) { + TestDescriptor td = new TestDescriptor(t); + if (focused != null && focused != t) { + td.setRegressionTest(false); // disable it + } + tests.add(td); } } 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 3843e50ca0..2c4637a269 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 @@ -290,6 +290,16 @@ public abstract class RuleTst { return extractTestsFromXml(rule, testsFileName); } + /** + * Extract a set of tests from an XML file. The file should be + * ./xml/RuleName.xml relative to the test class. The format is defined in + * test-data.xsd. + */ + RuleTestCollection parseTestCollection(Rule rule) { + String testsFileName = getCleanRuleName(rule); + return parseTestXml(rule, testsFileName, "xml/"); + } + public TestDescriptor[] extractTestsFromXml(Rule rule, String testsFileName) { return extractTestsFromXml(rule, testsFileName, "xml/"); } diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java index 06ad01f2c3..f24822d9ff 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java @@ -32,6 +32,7 @@ public class TestDescriptor { private boolean isRegressionTest = true; private boolean useAuxClasspath = true; private int numberInDocument = -1; + private boolean isFocused = false; public TestDescriptor() { // Empty default descriptor added to please mvn surefire plugin @@ -62,6 +63,7 @@ public class TestDescriptor { this.numberInDocument = td.getIndex(); this.properties = td.getProperties(); this.languageVersion = td.getLanguageVersion(); + this.isFocused = td.isFocused(); } public int getNumberInDocument() { From db430e64c56e235b3988debe5c1f011c482e0ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 22 Jul 2022 14:33:32 +0200 Subject: [PATCH 04/10] add deprecations --- .../pmd/testframework/RuleTst.java | 21 +++++++++++++++++++ .../pmd/testframework/TestDescriptor.java | 5 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) 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 2c4637a269..a8f898270b 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 @@ -30,6 +30,7 @@ import net.sourceforge.pmd.RuleSets; import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.RulesetsFactoryUtils; import net.sourceforge.pmd.SourceCodeProcessor; +import net.sourceforge.pmd.annotation.InternalApi; import net.sourceforge.pmd.lang.LanguageVersion; import net.sourceforge.pmd.properties.PropertyDescriptor; import net.sourceforge.pmd.renderers.TextRenderer; @@ -51,6 +52,8 @@ public abstract class RuleTst { /** * Find a rule in a certain ruleset by name + * + * todo make this static */ public Rule findRule(String ruleSet, String ruleName) { try { @@ -73,6 +76,8 @@ public abstract class RuleTst { * violations. */ @SuppressWarnings("unchecked") + @InternalApi + @Deprecated public void runTest(TestDescriptor test) { Rule rule = test.getRule(); @@ -218,10 +223,14 @@ public abstract class RuleTst { /** * Run the rule on the given code and put the violations in the report. */ + @InternalApi + @Deprecated public void runTestFromString(String code, Rule rule, Report report, LanguageVersion languageVersion) { runTestFromString(code, rule, report, languageVersion, true); } + @InternalApi + @Deprecated public void runTestFromString(String code, Rule rule, Report report, LanguageVersion languageVersion, boolean isUseAuxClasspath) { try { @@ -259,6 +268,8 @@ public abstract class RuleTst { } } + @InternalApi + @Deprecated public void runTestFromString(TestDescriptor test, Rule rule, Report report) { runTestFromString(test.getCode(), rule, report, test.getLanguageVersion(), test.isUseAuxClasspath()); } @@ -267,6 +278,8 @@ public abstract class RuleTst { * getResourceAsStream tries to find the XML file in weird locations if the * ruleName includes the package, so we strip it here. */ + @InternalApi + @Deprecated protected String getCleanRuleName(Rule rule) { String fullClassName = rule.getClass().getName(); if (fullClassName.equals(rule.getName())) { @@ -284,6 +297,8 @@ public abstract class RuleTst { * ./xml/RuleName.xml relative to the test class. The format is defined in * test-data.xsd. */ + @InternalApi + @Deprecated public TestDescriptor[] extractTestsFromXml(Rule rule) { String testsFileName = getCleanRuleName(rule); @@ -300,6 +315,8 @@ public abstract class RuleTst { return parseTestXml(rule, testsFileName, "xml/"); } + @InternalApi + @Deprecated public TestDescriptor[] extractTestsFromXml(Rule rule, String testsFileName) { return extractTestsFromXml(rule, testsFileName, "xml/"); } @@ -309,6 +326,8 @@ public abstract class RuleTst { * should be ./xml/[testsFileName].xml relative to the test class. The * format is defined in test-data.xsd. */ + @InternalApi + @Deprecated public TestDescriptor[] extractTestsFromXml(Rule rule, String testsFileName, String baseDirectory) { RuleTestCollection collection = parseTestXml(rule, testsFileName, baseDirectory); return toLegacyArray(collection); @@ -365,6 +384,8 @@ public abstract class RuleTst { /** * Run a set of tests of a certain sourceType. */ + @InternalApi + @Deprecated public void runTests(TestDescriptor[] tests) { for (int i = 0; i < tests.length; i++) { runTest(tests[i]); diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java index f24822d9ff..62fffc8189 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/TestDescriptor.java @@ -16,8 +16,11 @@ import net.sourceforge.pmd.test.schema.RuleTestDescriptor; /** * Stores the information required to run a complete test. + * + * @deprecated Use {@link RuleTestDescriptor} instead */ @Ignore("this is not a unit test") +@Deprecated public class TestDescriptor { private Rule rule; private Properties properties; @@ -32,7 +35,6 @@ public class TestDescriptor { private boolean isRegressionTest = true; private boolean useAuxClasspath = true; private int numberInDocument = -1; - private boolean isFocused = false; public TestDescriptor() { // Empty default descriptor added to please mvn surefire plugin @@ -63,7 +65,6 @@ public class TestDescriptor { this.numberInDocument = td.getIndex(); this.properties = td.getProperties(); this.languageVersion = td.getLanguageVersion(); - this.isFocused = td.isFocused(); } public int getNumberInDocument() { From ee5fa8ee94ba0407f255b54f8e5f01c03bd66624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 22 Jul 2022 14:53:45 +0200 Subject: [PATCH 05/10] Update docs --- docs/_plugins/jdoc_namespace_tag.rb | 2 +- docs/pages/pmd/userdocs/extending/testing.md | 12 ++++++++---- docs/pages/release_notes.md | 11 +++++++++-- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/docs/_plugins/jdoc_namespace_tag.rb b/docs/_plugins/jdoc_namespace_tag.rb index f6de2f0c49..f17070f01c 100644 --- a/docs/_plugins/jdoc_namespace_tag.rb +++ b/docs/_plugins/jdoc_namespace_tag.rb @@ -102,7 +102,7 @@ class JDocNamespaceDeclaration < Liquid::Tag RESERVED_NSPACES = ['apex', 'core', 'cpp', 'cs', 'dart', 'dist', 'doc', 'fortran', 'go', 'groovy', 'java', 'javascript', 'jsp', 'kotlin', 'lua', 'matlab', 'objectivec', 'perl', 'php', 'plsql', 'python', 'ruby', 'scala', 'swift', - 'test', 'ui', + 'test', 'test-schema', 'ui', 'modelica', 'visualforce', 'vm', 'xml'].flat_map {|m| [m, "pmd-" + m]} def self.make_base_namespaces diff --git a/docs/pages/pmd/userdocs/extending/testing.md b/docs/pages/pmd/userdocs/extending/testing.md index f33c74175b..7464dfd4af 100644 --- a/docs/pages/pmd/userdocs/extending/testing.md +++ b/docs/pages/pmd/userdocs/extending/testing.md @@ -135,14 +135,18 @@ between different test cases. The `` elements understands the following optional attributes: -* **reinitializeRule**: By default, it's `true`, so each test case starts with a fresh instantiated rule. Set it - to `false` to reproduce cases, where the previous run has influences. +* **disabled**: By default, it's `false`. Set it to `true`, to ignore and skip a test case. -* **disabled**: By default, it's `false`. Set ti to `true`, to ignore and skip a test case. +* **focused**: By default, it's `false`. Set it to `true`, to ignore all other test cases. -* **useAuxClasspath**: By default, it's `true`. Set it to `false` to reproduce issues which only +* **useAuxClasspath**: _deprecated since PMD 6.48.0: assumed true, has no effect anymore._ + By default, it's `true`. Set it to `false` to reproduce issues which only appear without type resolution. +* **reinitializeRule**: _deprecated since PMD 6.48.0: assumed true, has no effect anymore._ + By default, it's `true`, so each test case starts with a fresh instantiated rule. Set it + to `false` to reproduce cases, where the previous run has influences. + * **regressionTest**: _deprecated since PMD 6.48.0: Use `disabled` instead. Note: It has the opposite boolean semantic._ By default, it's `true`. Set it to `false`, to ignore and skip a test case. diff --git a/docs/pages/release_notes.md b/docs/pages/release_notes.md index 048c1bac00..1f10e291e3 100644 --- a/docs/pages/release_notes.md +++ b/docs/pages/release_notes.md @@ -54,6 +54,7 @@ Being based on a proper Antlr grammar, CPD can: * java-performance * [#3625](https://github.com/pmd/pmd/issues/3625): \[java] AddEmptyString - false negative with empty var * test + * [#3302](https://github.com/pmd/pmd/pull/3302): \[test] Improve xml test schema * [#3758](https://github.com/pmd/pmd/issues/3758): \[test] Move pmd-test to java 8 * [#3976](https://github.com/pmd/pmd/pull/3976): \[test] Extract xml schema module @@ -65,8 +66,12 @@ Being based on a proper Antlr grammar, CPD can: this module for testing your own custom rules, you'll need to make sure to use at least Java 8. * The new module "pmd-test-schema" contains now the XSD schema and the code to parse the rule test XML files. The schema has been extracted in order to easily share it with other tools like the Rule Designer or IDE plugins. -* The attribute `isRegressionTest` is deprecated and the new attribute `disabled` should be used instead for - defining whether a rule test should be skipped or not. +* Test schema changes: + * The attribute `isRegressionTest` of `test-code` is deprecated. The new + attribute `disabled` should be used instead for defining whether a rule test should be skipped or not. + * The attributes `reinitializeRule` and `useAuxClasspath` of `test-code` are deprecated and assumed true. + They will not be replaced. + * The new attribute `focused` of `test-code` allows disabling all tests except the focused one temporarily. * More information about the rule test framework can be found in the documentation: [Testing your rules](pmd_userdocs_extending_testing.html) @@ -77,6 +82,8 @@ Being based on a proper Antlr grammar, CPD can: but it is no longer supported with Java 19 Preview. * The interface {% jdoc core::cpd.renderer.CPDRenderer %} is deprecated. For custom CPD renderers the new interface {% jdoc core::cpd.renderer.CPDReportRenderer %} should be used. +* The class {% jdoc test::testframework.TestDescriptor %} is deprecated, replaced with {% jdoc test-schema::testframework.RuleTestDescriptor %}. +* Many methods of {% jdoc test::testframework.RuleTst %} have been deprecated as internal API. #### Experimental APIs From c1b8d6a5d83d5b8f95a9242030ada988b932ab64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Fri, 22 Jul 2022 17:30:54 +0200 Subject: [PATCH 06/10] Fix PMD warning --- .../java/net/sourceforge/pmd/testframework/RuleTestRunner.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java index 7e1e5606db..25b8d04641 100644 --- a/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java +++ b/pmd-test/src/main/java/net/sourceforge/pmd/testframework/RuleTestRunner.java @@ -72,7 +72,7 @@ public class RuleTestRunner extends ParentRunner { RuleTestDescriptor focused = ruleTests.getFocusedTestOrNull(); for (RuleTestDescriptor t : ruleTests.getTests()) { TestDescriptor td = new TestDescriptor(t); - if (focused != null && focused != t) { + if (focused != null && !focused.equals(t)) { td.setRegressionTest(false); // disable it } tests.add(td); From d9984ec92fad5c2d463f43a7009a0b84dc3d837f Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 22 Jul 2022 21:01:25 +0200 Subject: [PATCH 07/10] [test] Document deprecated attribute useAuxClasspath in schema --- .../net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd | 8 +++++++- .../java/net/sourceforge/pmd/testframework/RuleTst.java | 2 +- pmd-test/src/main/resources/rule-tests_1_0_0.xsd | 8 +++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd b/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd index 1a049af0b6..6d8b1d2ac5 100644 --- a/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd +++ b/pmd-test-schema/src/main/resources/net/sourceforge/pmd/test/schema/rule-tests_1_0_0.xsd @@ -73,7 +73,13 @@ - + + + + This attribute is deprecated, it is assumed true and ignored. + + + 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 a8f898270b..87e76589d0 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 @@ -308,7 +308,7 @@ public abstract class RuleTst { /** * Extract a set of tests from an XML file. The file should be * ./xml/RuleName.xml relative to the test class. The format is defined in - * test-data.xsd. + * rule-tests_1_0_0.xsd in pmd-test-schema. */ RuleTestCollection parseTestCollection(Rule rule) { String testsFileName = getCleanRuleName(rule); diff --git a/pmd-test/src/main/resources/rule-tests_1_0_0.xsd b/pmd-test/src/main/resources/rule-tests_1_0_0.xsd index 1a049af0b6..6d8b1d2ac5 100644 --- a/pmd-test/src/main/resources/rule-tests_1_0_0.xsd +++ b/pmd-test/src/main/resources/rule-tests_1_0_0.xsd @@ -73,7 +73,13 @@ - + + + + This attribute is deprecated, it is assumed true and ignored. + + + From cb5acd6389d48fe76293e3844277ffdeb932985c Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 22 Jul 2022 14:32:46 +0200 Subject: [PATCH 08/10] [java] Remove usages of reinitializeRule and useAuxClasspath in rule tests (#3976 / #3302) --- .../rule/codestyle/xml/MethodNamingConventions.xml | 3 ++- .../java/rule/design/xml/CyclomaticComplexity.xml | 2 +- .../java/rule/design/xml/StdCyclomaticComplexity.xml | 2 +- .../lang/java/rule/errorprone/xml/CloseResource.xml | 12 ++++++------ 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodNamingConventions.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodNamingConventions.xml index 8ce7e50716..d97bf1c5e5 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodNamingConventions.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/codestyle/xml/MethodNamingConventions.xml @@ -178,7 +178,8 @@ public class TournamentTest extends TestCase { ]]> - + + JUnit 4 test detection without proper auxclasspath 1 8 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml index 3a7c8fff48..287744daaf 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/CyclomaticComplexity.xml @@ -149,7 +149,7 @@ public class Test { - + #985 Suppressed methods shouldn't affect avg CyclomaticComplexity 2 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/StdCyclomaticComplexity.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/StdCyclomaticComplexity.xml index 43392c28f1..db9e947c2f 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/StdCyclomaticComplexity.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/design/xml/StdCyclomaticComplexity.xml @@ -164,7 +164,7 @@ public class Test { - + #985 Suppressed methods shouldn't affect avg CyclomaticComplexity 2 0 diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/CloseResource.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/CloseResource.xml index 0f63419bf2..292e4e0336 100644 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/CloseResource.xml +++ b/pmd-java/src/test/resources/net/sourceforge/pmd/lang/java/rule/errorprone/xml/CloseResource.xml @@ -249,7 +249,7 @@ public class Foo { ]]> - + invoke an external method that close the resource: bug 2920057 closeStatement,closeStatement,closeResultSet,closeConnexion java.sql.Connection,java.sql.Statement,java.sql.ResultSet,java.sql.PreparedStatement @@ -280,7 +280,7 @@ public class StructureFactory { ]]> - + invoke an external method that closes the resource, but one is not the right method and an another is not the right variable: see bug 2920057 closeStatement,closeStatement,closeResultSet,closeConnexion java.sql.Connection,java.sql.Statement,java.sql.ResultSet,java.sql.PreparedStatement @@ -312,7 +312,7 @@ public class StructureFactory { ]]> - + #1011 CloseResource Rule ignores Constructors 1 - + #1011 CloseResource Rule ignores Constructors - closed in finally 0 - + #1011 CloseResource Rule ignores Constructors - not a problem - instance variable 0 - + #1029 No instance level check in the close resource rule 0 Date: Fri, 22 Jul 2022 21:06:21 +0200 Subject: [PATCH 09/10] [test] Remove unused code from RuleTst --- .../pmd/testframework/RuleTst.java | 26 ++++--------------- .../pmd/testframework/RuleTstTest.java | 4 +++ 2 files changed, 9 insertions(+), 21 deletions(-) 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 87e76589d0..7768660bd7 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 @@ -81,9 +81,8 @@ public abstract class RuleTst { public void runTest(TestDescriptor test) { Rule rule = test.getRule(); - if (test.getReinitializeRule()) { - rule = reinitializeRule(rule); - } + // always reinitialize the rule, regardless of test.getReinitializeRule() (#3976 / #3302) + rule = reinitializeRule(rule); Map, Object> oldProperties = rule.getPropertiesByPropertyDescriptor(); try { @@ -237,24 +236,9 @@ public abstract class RuleTst { PMDConfiguration configuration = new PMDConfiguration(); configuration.setDefaultLanguageVersion(languageVersion); configuration.setIgnoreIncrementalAnalysis(true); - if (isUseAuxClasspath) { - // configure the "auxclasspath" option for unit testing - configuration.prependAuxClasspath("."); - } else { - // simple class loader, that doesn't delegate to parent. - // this allows us in the tests to simulate PMD run without - // auxclasspath, not even the classes from the test dependencies - // will be found. - configuration.setClassLoader(new ClassLoader() { - @Override - protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - if (name.startsWith("java.") || name.startsWith("javax.")) { - return super.loadClass(name, resolve); - } - throw new ClassNotFoundException(name); - } - }); - } + // regardless of isUseAuxClasspath the auxclasspath is always used (#3976 / #3302) + // configure the "auxclasspath" option for unit testing + configuration.prependAuxClasspath("."); RuleContext ctx = new RuleContext(); ctx.setReport(report); ctx.setSourceCodeFile(new File("n/a")); 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 index 8ea4f81b75..f4b3c58610 100644 --- a/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java +++ b/pmd-test/src/test/java/net/sourceforge/pmd/testframework/RuleTstTest.java @@ -36,6 +36,10 @@ public class RuleTstTest { private Rule rule = mock(Rule.class); private RuleTst ruleTester = new RuleTst() { + @Override + public Rule findRule(String ruleSet, String ruleName) { + return rule; + } }; @Test From 2f3f0d69609c5a27c07b56e2220801c6700ac40e Mon Sep 17 00:00:00 2001 From: Andreas Dangel Date: Fri, 22 Jul 2022 15:10:33 +0200 Subject: [PATCH 10/10] [java] Refactor RegexpAcceptanceTest --- .../pmd/jaxen/RegexpAcceptanceTest.java | 59 ++++++++++++++----- .../pmd/jaxen/xml/RegexpAcceptance.xml | 33 ----------- 2 files changed, 45 insertions(+), 47 deletions(-) delete mode 100644 pmd-java/src/test/resources/net/sourceforge/pmd/jaxen/xml/RegexpAcceptance.xml diff --git a/pmd-java/src/test/java/net/sourceforge/pmd/jaxen/RegexpAcceptanceTest.java b/pmd-java/src/test/java/net/sourceforge/pmd/jaxen/RegexpAcceptanceTest.java index 396c87a009..cba46f6d16 100644 --- a/pmd-java/src/test/java/net/sourceforge/pmd/jaxen/RegexpAcceptanceTest.java +++ b/pmd-java/src/test/java/net/sourceforge/pmd/jaxen/RegexpAcceptanceTest.java @@ -4,33 +4,64 @@ package net.sourceforge.pmd.jaxen; +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Before; import org.junit.Test; +import net.sourceforge.pmd.PMDConfiguration; +import net.sourceforge.pmd.PmdAnalysis; +import net.sourceforge.pmd.Report; import net.sourceforge.pmd.Rule; +import net.sourceforge.pmd.RuleSet; +import net.sourceforge.pmd.RuleViolation; import net.sourceforge.pmd.lang.LanguageRegistry; import net.sourceforge.pmd.lang.java.JavaLanguageModule; import net.sourceforge.pmd.lang.rule.XPathRule; -import net.sourceforge.pmd.testframework.SimpleAggregatorTst; -import net.sourceforge.pmd.testframework.TestDescriptor; +import net.sourceforge.pmd.lang.rule.xpath.XPathVersion; -public class RegexpAcceptanceTest extends SimpleAggregatorTst { +public class RegexpAcceptanceTest { private static final String XPATH = "//ClassOrInterfaceDeclaration[matches(@Image, 'F?o')]"; - @Override - protected void setUp() { - // not registering any rule + private Rule rule; + + @Before + public void setUp() { + rule = new XPathRule(XPathVersion.XPATH_1_0, XPATH); + rule.setLanguage(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)); + rule.setMessage("F?o matched"); } @Test - public void testSimple() { - Rule r = new XPathRule(XPATH); - r.setLanguage(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)); - r.setMessage(""); - TestDescriptor[] testDescriptors = extractTestsFromXml(r, "RegexpAcceptance"); - for (TestDescriptor testDescriptor : testDescriptors) { - testDescriptor.setReinitializeRule(false); + public void shouldMatchFoo() { + List violations = eval("public class Foo {}"); + assertEquals(1, violations.size()); + } + + @Test + public void shouldNotMatchBar() { + List violations = eval("public class Bar {}"); + assertEquals(0, violations.size()); + } + + @Test + public void shouldMatchFlo() { + List violations = eval("public class Flo {}"); + assertEquals(1, violations.size()); + } + + private List eval(String code) { + PMDConfiguration config = new PMDConfiguration(); + config.setIgnoreIncrementalAnalysis(true); + try (PmdAnalysis pmd = PmdAnalysis.create(config)) { + pmd.addRuleSet(RuleSet.forSingleRule(rule)); + pmd.files().addSourceFile(code, "RegexpAcceptanceTest.java"); + + Report report = pmd.performAnalysisAndCollectReport(); + return report.getViolations(); } - runTests(testDescriptors); } } diff --git a/pmd-java/src/test/resources/net/sourceforge/pmd/jaxen/xml/RegexpAcceptance.xml b/pmd-java/src/test/resources/net/sourceforge/pmd/jaxen/xml/RegexpAcceptance.xml deleted file mode 100644 index a42ecbdfa8..0000000000 --- a/pmd-java/src/test/resources/net/sourceforge/pmd/jaxen/xml/RegexpAcceptance.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - 1 - - - - - 0 - - - - - 1 - - - \ No newline at end of file