Skip to content

Commit

Permalink
Merge pull request #181 from TNG/freeze_rules
Browse files Browse the repository at this point in the history
Provide a way to store all current violations of a rule and successively only report new ones
  • Loading branch information
codecholeric committed Jul 4, 2019
2 parents 3f2bd42 + 296b8c6 commit 93a7cfc
Show file tree
Hide file tree
Showing 57 changed files with 2,362 additions and 234 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Class <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> implements interface <javax.persistence.EntityManager> in (ServiceViolatingDaoRules.java:0)
Field <com.tngtech.archunit.example.persistence.first.dao.jpa.SomeJpa.entityManager> has type <javax.persistence.EntityManager> in (SomeJpa.java:0)
Field <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.entityManager> has type <javax.persistence.EntityManager> in (OtherJpa.java:0)
Field <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.myEntityManager> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> in (ServiceViolatingDaoRules.java:0)
Method <com.tngtech.archunit.example.persistence.first.dao.jpa.SomeJpa.findById(long)> calls method <javax.persistence.EntityManager.find(java.lang.Class, java.lang.Object)> in (SomeJpa.java:20)
Method <com.tngtech.archunit.example.persistence.second.dao.OtherDao.getEntityManager()> has return type <javax.persistence.EntityManager> in (OtherDao.java:0)
Method <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.findById(long)> calls method <javax.persistence.EntityManager.find(java.lang.Class, java.lang.Object)> in (OtherJpa.java:19)
Method <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.getEntityManager()> has return type <javax.persistence.EntityManager> in (OtherJpa.java:0)
Method <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.testConnection()> calls method <javax.persistence.EntityManager.unwrap(java.lang.Class)> in (OtherJpa.java:24)
Method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.illegallyUseEntityManager()> calls method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager.persist(java.lang.Object)> in (ServiceViolatingDaoRules.java:27)
Method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.illegallyUseEntityManager()> calls method <javax.persistence.EntityManager.persist(java.lang.Object)> in (ServiceViolatingDaoRules.java:26)
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Class <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService> implements interface <com.tngtech.archunit.example.service.ServiceInterface> in (DaoCallingService.java:0)
Class <com.tngtech.archunit.example.service.impl.ServiceImplementation> implements interface <com.tngtech.archunit.example.service.ServiceInterface> in (ServiceImplementation.java:0)
Constructor <com.tngtech.archunit.example.SomeMediator.<init>(com.tngtech.archunit.example.service.ServiceViolatingLayerRules)> has parameter of type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeMediator.java:0)
Field <com.tngtech.archunit.example.SomeMediator.service> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeMediator.java:0)
Field <com.tngtech.archunit.example.controller.SomeController.otherService> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeController.java:0)
Field <com.tngtech.archunit.example.controller.SomeController.service> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules> in (SomeController.java:0)
Field <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService.service> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (DaoCallingService.java:0)
Field <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.myEntityManager> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> in (ServiceViolatingDaoRules.java:0)
Method <com.tngtech.archunit.example.SomeMediator.violateLayerRulesIndirectly()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.doSomething()> in (SomeMediator.java:15)
Method <com.tngtech.archunit.example.controller.SomeController.doSthController()> calls method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.doSthService()> in (SomeController.java:11)
Method <com.tngtech.archunit.example.controller.SomeController.doSthWithSecuredService()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.properlySecured()> in (SomeController.java:15)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> calls constructor <com.tngtech.archunit.example.service.ServiceHelper.<init>()> in (SomeGuiController.java:7)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> calls constructor <com.tngtech.archunit.example.service.ServiceHelper.<init>(java.lang.String)> in (SomeGuiController.java:8)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> gets field <com.tngtech.archunit.example.service.ServiceHelper.insecure> in (SomeGuiController.java:10)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> gets field <com.tngtech.archunit.example.service.ServiceHelper.properlySecured> in (SomeGuiController.java:11)
Method <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService.violateLayerRules()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.doSomething()> in (DaoCallingService.java:14)
Method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.illegallyUseEntityManager()> calls method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager.persist(java.lang.Object)> in (ServiceViolatingDaoRules.java:27)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
#Sun Jun 09 01:50:44 ICT 2019
no\ classes\ should\ depend\ on\ classes\ that\ reside\ in\ a\ package\ '..service..'=d8e3c650-e214-402f-8cfa-33a8607785d3
no\ classes\ should\ depend\ on\ classes\ that\ are\ assignable\ to\ javax.persistence.EntityManager=6f3a1e55-3673-4950-a3be-857751b3d515
4 changes: 4 additions & 0 deletions archunit-example/example-junit4/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ ext.moduleName = 'com.tngtech.archunit.example.junit4'
dependencies {
testCompile project(path: ':archunit-junit4')
testCompile project(path: ':archunit-example:example-plain')

testRuntime dependency.log4j_api
testRuntime dependency.log4j_core
testRuntime dependency.log4j_slf4j
}

test {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.tngtech.archunit.exampletest.junit4;

import javax.persistence.EntityManager;

import com.tngtech.archunit.ArchConfiguration;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.junit.ArchUnitRunner;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.library.freeze.FreezingArchRule;
import com.tngtech.archunit.library.freeze.ViolationLineMatcher;
import com.tngtech.archunit.library.freeze.ViolationStore;
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.library.freeze.FreezingArchRule.freeze;

/**
* This test demonstrates the use of {@link FreezingArchRule} with 'default' configuration.
* While both rules shown have numerous violations, most of those violations have been 'frozen', i.e. at some point in time all violations
* were recorded as accepted for the moment. Only violations added afterwards will be reported.<br>
* You can see how the default text based {@link ViolationStore} stores the results under {@code src/test/resources/frozen} configured
* via {@value ArchConfiguration#ARCHUNIT_PROPERTIES_RESOURCE_NAME}. You can also
* observe that if you fix an old violation, this store will automatically be adjusted to not allow any regression.<br>
* Furthermore you can observe how the default {@link ViolationLineMatcher} will ignore changes in line numbers of recorded violations,
* i.e. if you only change the line numbers of frozen violations, the test will still pass.
*/
@Category(Example.class)
@RunWith(ArchUnitRunner.class)
@AnalyzeClasses(packages = "com.tngtech.archunit.example")
public class FrozenRulesTest {

@ArchTest
public static final ArchRule no_classes_should_depend_on_service =
freeze(noClasses().should().dependOnClassesThat().resideInAPackage("..service.."));

@ArchTest
public static final ArchRule no_classes_should_use_the_EntityManager =
freeze(noClasses().should().dependOnClassesThat().areAssignableTo(EntityManager.class));
}

Original file line number Diff line number Diff line change
@@ -1 +1 @@
resolveMissingDependenciesFromClassPath=true
freeze.store.default.path=src/test/resources/frozen
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Class <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService> implements interface <com.tngtech.archunit.example.service.ServiceInterface> in (DaoCallingService.java:0)
Class <com.tngtech.archunit.example.service.impl.ServiceImplementation> implements interface <com.tngtech.archunit.example.service.ServiceInterface> in (ServiceImplementation.java:0)
Constructor <com.tngtech.archunit.example.SomeMediator.<init>(com.tngtech.archunit.example.service.ServiceViolatingLayerRules)> has parameter of type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeMediator.java:0)
Field <com.tngtech.archunit.example.SomeMediator.service> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeMediator.java:0)
Field <com.tngtech.archunit.example.controller.SomeController.otherService> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeController.java:0)
Field <com.tngtech.archunit.example.controller.SomeController.service> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules> in (SomeController.java:0)
Field <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService.service> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (DaoCallingService.java:0)
Field <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.myEntityManager> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> in (ServiceViolatingDaoRules.java:0)
Method <com.tngtech.archunit.example.SomeMediator.violateLayerRulesIndirectly()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.doSomething()> in (SomeMediator.java:15)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> calls constructor <com.tngtech.archunit.example.service.ServiceHelper.<init>()> in (SomeGuiController.java:7)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> calls constructor <com.tngtech.archunit.example.service.ServiceHelper.<init>(java.lang.String)> in (SomeGuiController.java:8)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> gets field <com.tngtech.archunit.example.service.ServiceHelper.insecure> in (SomeGuiController.java:10)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> gets field <com.tngtech.archunit.example.service.ServiceHelper.properlySecured> in (SomeGuiController.java:11)
Method <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService.violateLayerRules()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.doSomething()> in (DaoCallingService.java:14)
Method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.illegallyUseEntityManager()> calls method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager.persist(java.lang.Object)> in (ServiceViolatingDaoRules.java:27)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Class <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> implements interface <javax.persistence.EntityManager> in (ServiceViolatingDaoRules.java:0)
Field <com.tngtech.archunit.example.persistence.first.dao.jpa.SomeJpa.entityManager> has type <javax.persistence.EntityManager> in (SomeJpa.java:0)
Field <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.entityManager> has type <javax.persistence.EntityManager> in (OtherJpa.java:0)
Field <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.myEntityManager> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> in (ServiceViolatingDaoRules.java:0)
Method <com.tngtech.archunit.example.persistence.first.dao.jpa.SomeJpa.findById(long)> calls method <javax.persistence.EntityManager.find(java.lang.Class, java.lang.Object)> in (SomeJpa.java:20)
Method <com.tngtech.archunit.example.persistence.second.dao.OtherDao.getEntityManager()> has return type <javax.persistence.EntityManager> in (OtherDao.java:0)
Method <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.findById(long)> calls method <javax.persistence.EntityManager.find(java.lang.Class, java.lang.Object)> in (OtherJpa.java:19)
Method <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.getEntityManager()> has return type <javax.persistence.EntityManager> in (OtherJpa.java:0)
Method <com.tngtech.archunit.example.persistence.second.dao.jpa.OtherJpa.testConnection()> calls method <javax.persistence.EntityManager.unwrap(java.lang.Class)> in (OtherJpa.java:24)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#
#Sun Jun 09 00:30:33 ICT 2019
no\ classes\ should\ depend\ on\ classes\ that\ reside\ in\ a\ package\ '..service..'=a81a2b54-5a18-4145-b544-7a580aba0425
no\ classes\ should\ depend\ on\ classes\ that\ are\ assignable\ to\ javax.persistence.EntityManager=e77ec262-4d5c-4a7b-b41f-362a71e5a1d8
4 changes: 4 additions & 0 deletions archunit-example/example-junit5/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ dependencies {
testCompile project(path: ':archunit-example:example-plain')

testRuntime project(path: ':archunit-junit5-engine')

testRuntime dependency.log4j_api
testRuntime dependency.log4j_core
testRuntime dependency.log4j_slf4j
}

test {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.tngtech.archunit.exampletest.junit5;

import javax.persistence.EntityManager;

import com.tngtech.archunit.ArchConfiguration;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTag;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.library.freeze.FreezingArchRule;
import com.tngtech.archunit.library.freeze.ViolationLineMatcher;
import com.tngtech.archunit.library.freeze.ViolationStore;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.library.freeze.FreezingArchRule.freeze;

/**
* This test demonstrates the use of {@link FreezingArchRule} with 'default' configuration.
* While both rules shown have numerous violations, most of those violations have been 'frozen', i.e. at some point in time all violations
* were recorded as accepted for the moment. Only violations added afterwards will be reported.<br>
* You can see how the default text based {@link ViolationStore} stores the results under {@code src/test/resources/frozen} configured
* via {@value ArchConfiguration#ARCHUNIT_PROPERTIES_RESOURCE_NAME}. You can also
* observe that if you fix an old violation, this store will automatically be adjusted to not allow any regression.<br>
* Furthermore you can observe how the default {@link ViolationLineMatcher} will ignore changes in line numbers of recorded violations,
* i.e. if you only change the line numbers of frozen violations, the test will still pass.
*/
@ArchTag("example")
@AnalyzeClasses(packages = "com.tngtech.archunit.example")
public class FrozenRulesTest {

@ArchTest
static final ArchRule no_classes_should_depend_on_service =
freeze(noClasses().should().dependOnClassesThat().resideInAPackage("..service.."));

@ArchTest
static final ArchRule no_classes_should_use_the_EntityManager =
freeze(noClasses().should().dependOnClassesThat().areAssignableTo(EntityManager.class));
}

Original file line number Diff line number Diff line change
@@ -1 +1 @@
resolveMissingDependenciesFromClassPath=true
freeze.store.default.path=src/test/resources/frozen
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Class <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService> implements interface <com.tngtech.archunit.example.service.ServiceInterface> in (DaoCallingService.java:0)
Class <com.tngtech.archunit.example.service.impl.ServiceImplementation> implements interface <com.tngtech.archunit.example.service.ServiceInterface> in (ServiceImplementation.java:0)
Constructor <com.tngtech.archunit.example.SomeMediator.<init>(com.tngtech.archunit.example.service.ServiceViolatingLayerRules)> has parameter of type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeMediator.java:0)
Field <com.tngtech.archunit.example.SomeMediator.service> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeMediator.java:0)
Field <com.tngtech.archunit.example.controller.SomeController.otherService> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (SomeController.java:0)
Field <com.tngtech.archunit.example.controller.SomeController.service> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules> in (SomeController.java:0)
Field <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService.service> has type <com.tngtech.archunit.example.service.ServiceViolatingLayerRules> in (DaoCallingService.java:0)
Field <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.myEntityManager> has type <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager> in (ServiceViolatingDaoRules.java:0)
Method <com.tngtech.archunit.example.SomeMediator.violateLayerRulesIndirectly()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.doSomething()> in (SomeMediator.java:15)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> calls constructor <com.tngtech.archunit.example.service.ServiceHelper.<init>()> in (SomeGuiController.java:7)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> calls constructor <com.tngtech.archunit.example.service.ServiceHelper.<init>(java.lang.String)> in (SomeGuiController.java:8)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> gets field <com.tngtech.archunit.example.service.ServiceHelper.insecure> in (SomeGuiController.java:10)
Method <com.tngtech.archunit.example.controller.SomeGuiController.callServiceLayer()> gets field <com.tngtech.archunit.example.service.ServiceHelper.properlySecured> in (SomeGuiController.java:11)
Method <com.tngtech.archunit.example.persistence.layerviolation.DaoCallingService.violateLayerRules()> calls method <com.tngtech.archunit.example.service.ServiceViolatingLayerRules.doSomething()> in (DaoCallingService.java:14)
Method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules.illegallyUseEntityManager()> calls method <com.tngtech.archunit.example.service.ServiceViolatingDaoRules$MyEntityManager.persist(java.lang.Object)> in (ServiceViolatingDaoRules.java:27)

0 comments on commit 93a7cfc

Please sign in to comment.