Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Jira
serverONAP JIRA
columnskey,summary,type,created,updated,due,assignee,reporter,priority,status,resolution
serverId425b2b0a-557c-3c0c-b515-579789cceedb
keyCPS-347

We are proposing the introduction of automatic tools to support architecture and design quality during all application life cycle.

...

Code Block
languagejava
/**
 * 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
languagetext
[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)

...