Skip to content

Analyse the test sources with PMD - #218

Merged
MarkusPaulsen merged 5 commits into
mainfrom
chore/pmd-test-sources
Aug 27, 2026
Merged

Analyse the test sources with PMD#218
MarkusPaulsen merged 5 commits into
mainfrom
chore/pmd-test-sources

Conversation

@MarkusPaulsen

@MarkusPaulsen MarkusPaulsen commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

PMD never looked at the test tree, which is where the code that decides whether a violation was detected lives. It does now. Of 102 findings, 46 are in fixtures and excluded, 41 are false positives and suppressed individually, and 15 were real and are fixed. One of them was a test helper that ignored the value it claimed to check.

Linked issues

No linked issues

1. Problem

maven-pmd-plugin ran without includeTests, so src/test/java was never analysed. That is the half of the repository that decides whether a security violation was detected, and therefore the half whose defects fail silently: a test that asserts nothing still passes.

The clearest example found by turning it on: ThreadTest.assertThreadErrorMessage took an operationText parameter, documented it as "the specific operation text to check in the exception message", and never read it. Fifteen call sites passed distinct values. All fifteen were checked against the same hardcoded string instead.

2. Improvement from the user's perspective

No Improvement from the user's perspective

3. Improvement from the maintainer's perspective

The test tree is now held to the same rules as the main tree, so dead helpers, unused constants and swallowed results are reported rather than accumulated.

The boundary drawn here is not "main against test" but "assertion against the thing being asserted about". Fixtures are excluded in the ruleset, with the reasoning recorded next to the patterns: an empty catch block in the harness is a swallowed failure, while in a fixture it is the behaviour under test, and MaliciousExceptionB discards the result of a forbidden file read because that read is the attack. Cleaning either up would change what the suite measures while leaving it green.

4. Testing manual

Prerequisites

  1. A checkout of this branch and a JDK.

Steps

Not reproducible from an exercise. This changes the build and the test tree.

  1. Run mvn test-compile pmd:check. The compile has to come first, because PMD reads the compiled classes to tell a used wildcard import from an unused one, so a bare mvn pmd:check on a fresh checkout reports every wildcard import as unused and fails. CI compiles before the goal for the same reason.
  2. Run mvn test -Punit-core-tests,coverage.
  3. Run mvn test -Pcoverage -Dtest=de.tum.cit.ase.ares.integration.ThreadTest.
  4. Read the comment above assertThreadErrorMessage in ThreadTest.java and the exclusion block in .settings/pmd-rules.xml.

Expected result

Step 1 reports no violations. Step 2 reports 774 tests with no failures. Step 3 reports 20 tests with no failures. Step 4 shows why the parameter was removed rather than wired up, and which paths count as fixtures.

The parameter was removed rather than used because using it fails 14 of those 20 tests: the callers pass the console output the subject would have printed, such as "Task 2 executed", while the message names the intercepted call, for example "tried to illegally create Thread ... via ExecutorService.submit". The two were never the same thing.

Negative case (what must still be rejected)

The remaining assertion in assertThreadErrorMessage must still require "create Thread" in the message, so a thread-creation violation that stops being reported as such still fails the test. Confirm by reading the method: six substrings are still required.

Excluding the fixture paths must not exclude the harness. Confirm by checking that .settings/pmd-rules.xml lists only subject/, astTestFiles, example/student, org/apache/xyz, testuser and *Probe.java.

Modes exercised

No mode-specific behaviour changed.

  • ArchUnit + AspectJ
  • ArchUnit + instrumentation
  • WALA + AspectJ
  • WALA + instrumentation

5. Test case coverage regarding this PR

No production Java code changed

Breaking changes and migration

No breaking changes or migration.

Checklist

  • CI is green, or every remaining failure is explained above.
  • No secrets, tokens or absolute local paths are contained in the diff.

Review progress

  • Code review
  • Manual test

The test tree holds the harness that decides whether a security violation was detected,
and it was the one part of the code PMD never looked at.

Enabling it reported 102 findings, which sort into three kinds rather than one:

- 46 in fixtures. subject/, astTestFiles, example/student, org/apache/xyz and testuser
  are test input that happens to be written in Java. An empty catch block there is the
  behaviour under test, and MaliciousExceptionB discards the result of a forbidden file
  read because that read is the attack. Cleaning any of it up would change what the
  suite measures while leaving it green. Excluded in the ruleset, with that reasoning
  recorded next to the patterns.
- 41 false positives: strictTimeoutTarget() carries an annotation read reflectively,
  and three MockedStatic or ServerSocket resources exist to scope a mock or complete a
  connection rather than to be read. Suppressed individually, each with its reason.
  AvoidUsingHardCodedIP fires 38 times in four classes whose subject is the parsing of
  loopback addresses, suppressed per class rather than by disabling the rule, which
  would have disarmed it for main sources too.
- 15 real defects, fixed: five dead constants, one dead helper, three unused imports.

The last one was not dead code. ThreadTest.assertThreadErrorMessage took an
operationText the body never read while its javadoc claimed it was checked. Wiring it
up fails 14 of 20 tests, because the callers pass the console output the subject would
have printed ("Task 2 executed") while the message names the intercepted call ("tried
to illegally create Thread ... via ExecutorService.submit"). The parameter was never
the right thing to assert on, so it is gone from the signature and all 15 call sites,
and the note explaining that stays where the next person will find it.
@MarkusPaulsen
MarkusPaulsen requested a review from a team August 26, 2026 15:13
@MarkusPaulsen
MarkusPaulsen requested review from a team and krusche as code owners August 26, 2026 15:13
@coderabbitai

coderabbitai Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bf6e0de5-8b67-4887-b7ed-1f864f0fa8c4


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@MarkusPaulsen MarkusPaulsen reopened this Aug 27, 2026
@github-actions github-actions Bot added aop Automated area label: aop architecture Automated area label: architecture policy Automated area label: policy tests Automated area label: tests securitytest Automated area label: securitytest other Automated area label: other labels Aug 27, 2026
Enabling PMD on the test sources surfaced 19 UnnecessaryImport findings, all
false positives: the types they bring in (@Userbased, @UserTestResults,
@Testtest and the LocaleUser/structural fixtures) are used exclusively as
annotations or as .class literals, and PMD 7.17.0 does not count those uses
against an on-demand import, so it reports the import as unused even though
removing it breaks compilation.

Replace the flagged wildcard imports with explicit single-type imports of the
types each test actually uses. This removes the ambiguity that trips PMD while
keeping compilation identical. ThreadTest loses its UserBased import outright,
since its only @Userbased use is commented out.
@github-actions github-actions Bot added the ast Automated area label: ast label Aug 27, 2026
Markus Paulsen added 3 commits August 27, 2026 09:54
Running CPD over the test sources surfaces 11 cross-file duplication groups
that are legitimate: the astTestFiles structural fixtures are deliberately
similar (they are the subjects the structural analysis is checked against),
and the parallel *PathAdviceTest / Essential*Test / forbidden-vs-architecture
SystemAccessTest pairs mirror each other on purpose. Add these complete file
sets to the accepted baseline; the within-file duplication is fixed in code
instead.
Extract the repeated Mockito arrange blocks into shared private helpers so the
same setup is written once per test class:
- JavaWriterTest: stubArchitectureModeDefaults/stubAopModeDefaults/stubFileToolsDefaults/stubPhobosDefaults
- JavaCreatorTest: common arrange moved to nested-class fields plus stubClasspathAndArchitecture
- SecurityPolicyReaderAndDirectorTest: stubReaderAndDirectorChain
- JavaWriter/Network/FileSystem extractor tests: sample permission list builders
- WalaRuleTest: fold four near-identical CGNode builders into applicationNode
Behaviour is unchanged: every affected test class still passes, and the
verify(...) assertions keep their original specific argument matchers.
Run spotless:apply on the classes touched by the import and CPD-duplication
changes so they satisfy the Static Code Analysis Spotless gate (line wrapping
and import layout only, no behaviour change).
@MarkusPaulsen
MarkusPaulsen merged commit 878cfbc into main Aug 27, 2026
17 of 21 checks passed
@MarkusPaulsen
MarkusPaulsen deleted the chore/pmd-test-sources branch August 27, 2026 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aop Automated area label: aop architecture Automated area label: architecture ast Automated area label: ast other Automated area label: other policy Automated area label: policy securitytest Automated area label: securitytest tests Automated area label: tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant