...
Code Block | ||
---|---|---|
| ||
/** * Test class responsible for dependencies validations. */ @AnalyzeClasses(packages = "org.onap.cps", importOptions = { ImportOption.DoNotIncludeTests.class }) public class DependencyArchitectureTest { @ArchTest static final ArchRule noCyclesRule = slices().matching("org.onap.cps.(**)..").should().beFreeOfCycles(); @ArchTest static final ArchRule noUpperPackageDependencyRule = NO_CLASSES_SHOULD_DEPEND_UPPER_PACKAGES; } /** * Test class responsible for layered architecture. */ @AnalyzeClasses(packages = "org.onap.cps", importOptions = { ImportOption.DoNotIncludeTests.class }) public class LayeredArchitectureTest { private static final String A_CONTROLLER_PACKAGE = "org.onap.cps.controller.."; private static final String A_SERVICE_PACKAGE = "org.onap.cps.service.."; private static final String A_REPOSITORY_PACKAGE = "org.onap.cps.repository.."; @ArchTest public static final ArchRule layeredArchitectureRule = layeredArchitecture() .layer("Controller").definedBy(A_CONTROLLER_PACKAGE) .layer("Service").definedBy(A_SERVICE_PACKAGE) .layer("Repository").definedBy(A_REPOSITORY_PACKAGE) .whereLayer("Controller").mayNotBeAccessedByAnyLayer() .whereLayer("Service").mayOnlyBeAccessedByLayers("Controller") .whereLayer("Repository").mayOnlyBeAccessedByLayers("Service"); // 'access' catches only violations by real accesses, // i.e. accessing a field, calling a method; compare 'dependOn' further down @ArchTest public static final ArchRule controllerAccessRule = classes().that().resideInAPackage(A_CONTROLLER_PACKAGE) .should().onlyBeAccessed().byAnyPackage(A_CONTROLLER_PACKAGE); @ArchTest public static final ArchRule serviceAccessRule = classes().that().resideInAPackage(A_SERVICE_PACKAGE) .should().onlyBeAccessed().byAnyPackage(A_CONTROLLER_PACKAGE, A_SERVICE_PACKAGE); @ArchTest public static final ArchRule repositoryAccessRule = classes().that().resideInAPackage(A_REPOSITORY_PACKAGE) .should().onlyBeAccessed().byAnyPackage(A_SERVICE_PACKAGE, A_REPOSITORY_PACKAGE); // 'dependOn' catches a wider variety of violations, // e.g. having fields of type, having method parameters of type, extending type ... @ArchTest static final ArchRule controllerDependencyRule = classes().that().resideInAPackage(A_CONTROLLER_PACKAGE) .should().onlyHaveDependentClassesThat() .resideInAPackage(A_CONTROLLER_PACKAGE); @ArchTest static final ArchRule serviceDependencyRule = classes().that().resideInAPackage(A_SERVICE_PACKAGE) .should().onlyHaveDependentClassesThat() .resideInAnyPackage(A_CONTROLLER_PACKAGE, A_SERVICE_PACKAGE); @ArchTest static final ArchRule repositoryDependencyRule = classes().that().resideInAPackage(A_REPOSITORY_PACKAGE) .should().onlyHaveDependentClassesThat() .resideInAnyPackage(A_SERVICE_PACKAGE, A_REPOSITORY_PACKAGE); } |
Finding example:
Code Block | ||
---|---|---|
| ||
[ERROR] Failures: [ERROR] Architecture Violation [Priority: MEDIUM] - Rule 'slices matching 'org.onap.cps.(**)..' should be free of cycles' was violated (1 times): Cycle detected: Slice spi.model -> Slice utils -> Slice spi.model Dependencies of Slice spi.model Method <org.onap.cps.spi.model.DataNodeBuilder.addYangContainer(org.onap.cps.spi.model.DataNode, org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode)> calls method <org.onap.cps.utils.YangUtils.buildXpath(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier$PathArgument)> in (DataNodeBuilder.java:175) Dependencies of Slice utils Method <org.onap.cps.utils.DataMapUtils.lambda$containerElementsAsMap$2(org.onap.cps.spi.model.DataNode)> has parameter of type <org.onap.cps.spi.model.DataNode> in (DataMapUtils.java:0) Method <org.onap.cps.utils.DataMapUtils.lambda$containerElementsAsMap$3(org.onap.cps.spi.model.DataNode)> has parameter of type <org.onap.cps.spi.model.DataNode> in (DataMapUtils.java:0) Method <org.onap.cps.utils.DataMapUtils.lambda$listElementsAsMap$0(org.onap.cps.spi.model.DataNode)> has parameter of type <org.onap.cps.spi.model.DataNode> in (DataMapUtils.java:0) Method <org.onap.cps.utils.DataMapUtils.lambda$listElementsAsMap$1(org.onap.cps.spi.model.DataNode)> has parameter of type <org.onap.cps.spi.model.DataNode> in (DataMapUtils.java:0) Method <org.onap.cps.utils.DataMapUtils.toDataMap(org.onap.cps.spi.model.DataNode)> has parameter of type <org.onap.cps.spi.model.DataNode> in (DataMapUtils.java:0) Method <org.onap.cps.utils.DataMapUtils.toDataMap(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getLeaves()> in (DataMapUtils.java:48) Method <org.onap.cps.utils.DataMapUtils.toDataMap(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getChildDataNodes()> in (DataMapUtils.java:49) Method <org.onap.cps.utils.DataMapUtils.toDataMap(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getChildDataNodes()> in (DataMapUtils.java:50) Method <org.onap.cps.utils.DataMapUtils.lambda$listElementsAsMap$0(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getXpath()> in (DataMapUtils.java:61) Method <org.onap.cps.utils.DataMapUtils.lambda$listElementsAsMap$1(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getXpath()> in (DataMapUtils.java:63) Method <org.onap.cps.utils.DataMapUtils.lambda$containerElementsAsMap$2(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getXpath()> in (DataMapUtils.java:74) Method <org.onap.cps.utils.DataMapUtils.lambda$containerElementsAsMap$3(org.onap.cps.spi.model.DataNode)> calls method <org.onap.cps.spi.model.DataNode.getXpath()> in (DataMapUtils.java:77) |
...