Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #12099: Add ArchUnit test to detect cycles in packages #12190

Merged
merged 1 commit into from
Sep 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .ci/jsoref-spellchecker/exclude.pl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
^cdg-pitest-licence.txt$
^.teamcity/
^.ci/checker-framework-suppressions/
^config/archunit-store/
);
my $exclude = join "|", @excludes;
while (<>) {
Expand Down
2,776 changes: 2,776 additions & 0 deletions config/archunit-store/slices_should_be_free_of_cycles_suppressions

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions config/archunit-store/stored.rules
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
slices\ matching\ 'com.puppycrawl.tools.checkstyle.(**)'\ should\ be\ free\ of\ cycles=slices_should_be_free_of_cycles_suppressions
8 changes: 8 additions & 0 deletions config/checkstyle_non_main_files_suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@
<suppress checks="NewlineAtEndOfFile"
files="[\\/]test[\\/].*[\\/]checks[\\/]uniqueproperties[\\/]InputUniquePropertiesWithDuplicates\.properties"/>

<!-- ArchUnit store is automatically updated by ArchUnit which
does not add new line at the end. -->
<suppress checks="NewlineAtEndOfFile"
files="config[\\/]archunit-store[\\/]slices_should_be_free_of_cycles_suppressions"/>

<!-- till https://issues.apache.org/jira/browse/MRELEASE-1008 -->
<suppress id="lineLength" files="pom.xml"/>
<!-- this file cannot be line wraped -->
Expand Down Expand Up @@ -98,6 +103,9 @@
<!-- this file cannot be line wrapped, it contains cdg pitest licence -->
<suppress id="lineLength" files="cdg-pitest-licence.txt"/>

<!-- files in this directory cannot be line wrapped as they are generated by ArchUnit -->
<suppress id="lineLength" files="config[\\/]archunit-store.*"/>

<!-- apply check numberOfTestCasesInXpath only for files in suppressionxpathfilter directory -->
<suppress id="numberOfTestCasesInXpath"
files="src[\\/]it[\\/]java[\\/]com[\\/].*" />
Expand Down
6 changes: 4 additions & 2 deletions config/pmd-test.xml
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@
from the test method.
In XdocsPagesTest PMD does not find asserts in lambdas.
All test classes which starts with XpathRegression have asserts inside parent's method.
In ArchUnitTest, ArchUnitSuperClassTest, ImmutabilityTest assertion calls are not
required as they are called by the library -->
In ArchUnitTest, ArchUnitSuperClassTest, ImmutabilityTest, ArchUnitCyclesCheckTest
assertion calls are not required as they are called by the library -->
<property name="violationSuppressXPath"
value="//ClassOrInterfaceDeclaration[@SimpleName='AllChecksTest'
or @SimpleName='AstRegressionTest'
Expand All @@ -138,6 +138,8 @@
| //ClassOrInterfaceDeclaration[@SimpleName='ArchUnitTest']
//MethodDeclaration
| //ClassOrInterfaceDeclaration[@SimpleName='ArchUnitSuperClassTest']
//MethodDeclaration
| //ClassOrInterfaceDeclaration[@SimpleName='ArchUnitCyclesCheckTest']
//MethodDeclaration"/>
</properties>
</rule>
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1641,6 +1641,7 @@
<exclude>markdownlint.rb</exclude>
<exclude>signatures.txt</exclude>
<exclude>signatures-test.txt</exclude>
<exclude>archunit-store/**</exclude>
</excludes>
</validationSet>
<validationSet>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
// Copyright (C) 2001-2022 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
///////////////////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.internal;

import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices;

import org.junit.jupiter.api.Test;

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.library.freeze.FreezingArchRule;

public class ArchUnitCyclesCheckTest {

/**
* This test checks that
* <a href="https://www.archunit.org/userguide/html/000_Index.html#_slices">slices</a> should
* be free of
* <a href="https://www.archunit.org/userguide/html/000_Index.html#_cycle_checks">cycles</a>.
* In this particular test, each slice is a different package. Currently the violations from
* this test are frozen using
* <a href="https://www.archunit.org/userguide/html/000_Index.html#_freezing_arch_rules">
* FreezingArchRule</a>.
*
* <p>Whenever a new cycle is introduced or removed, the test will pass successfully but the
* frozen violations will be updated. It is highly recommended to avoid new cycles and, it
rnveach marked this conversation as resolved.
Show resolved Hide resolved
* is preferred to remove them. In both cases commit the changes for further discussion.
*
* <p>The frozen violations are present in {@code config/archunit-store} directory.
*/
@Test
public void testSlicesShouldBeFreeOfCycles() {
final JavaClasses importedClasses = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.puppycrawl.tools.checkstyle");

final ArchRule slicesShouldBeFreeOfCycles = FreezingArchRule.freeze(
slices()
.matching("com.puppycrawl.tools.checkstyle.(**)")
.should().beFreeOfCycles());

slicesShouldBeFreeOfCycles.check(importedClasses);
}
}
17 changes: 17 additions & 0 deletions src/test/resources/archunit.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# This will limit the maximum number of dependencies to report per cycle edge.
# Note that ArchUnit will regardless always analyze all dependencies to detect cycles,
# so this purely affects how many dependencies will be printed in the report.
# Also note that this number will quickly affect the required heap since it scales with number.
# of edges and number of cycles
# default is 20
cycles.maxNumberOfDependenciesPerEdge=550

# This will limit the maximum number of cycles to detect and thus required CPU and heap.
# default is 100
cycles.maxNumberToDetect=200

# The store will be updated with the current state, and the reported result will be success.
# Just like freezing violation for the first time while creating the store.
freeze.refreeze=true

freeze.store.default.path=config/archunit-store