Springboot Integration tests improvements 07/133007/3
authorlukegleeson <luke.gleeson@est.tech>
Wed, 11 Jan 2023 09:45:53 +0000 (09:45 +0000)
committerlukegleeson <luke.gleeson@est.tech>
Wed, 25 Jan 2023 17:40:32 +0000 (17:40 +0000)
Creation of CpsIntegrationSpecBase
Demonstration of test class implementing CpsIntegrationSpecBase in CpsPersistenceSpec
Tests use reduced liquibase steps, basic bookstore yang model and bookstore json payload

Issue-ID: CPS-1379
Signed-off-by: lukegleeson <luke.gleeson@est.tech>
Change-Id: I38202d0888808d08d85fce1aab45fc43e8b0cec3

12 files changed:
cps-ri/src/main/java/org/onap/cps/spi/repository/AnchorRepository.java
integration-test/pom.xml [new file with mode: 0644]
integration-test/src/test/groovy/org/onap/cps/integration/CpsIntegrationSpecBase.groovy [new file with mode: 0644]
integration-test/src/test/groovy/org/onap/cps/integration/CpsPersistenceSpec.groovy [new file with mode: 0644]
integration-test/src/test/groovy/org/onap/cps/integration/TestConfig.groovy [new file with mode: 0644]
integration-test/src/test/java/org/onap/cps/integration/DatabaseTestContainer.java [new file with mode: 0644]
integration-test/src/test/resources/application.yml [new file with mode: 0644]
integration-test/src/test/resources/data/BookstoreDataNodes.json [new file with mode: 0644]
integration-test/src/test/resources/data/bookstore.yang [new file with mode: 0644]
integration-test/src/test/resources/hibernate.cfg.xml [new file with mode: 0644]
integration-test/src/test/resources/liquibase/test-changelog.yaml [new file with mode: 0644]
pom.xml

index 471f175..3dbd578 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
- *  Modifications Copyright (C) 2021 Nordix Foundation
+ *  Modifications Copyright (C) 2021-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -30,7 +30,9 @@ import org.onap.cps.spi.exceptions.AnchorNotFoundException;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.query.Param;
+import org.springframework.stereotype.Repository;
 
+@Repository
 public interface AnchorRepository extends JpaRepository<AnchorEntity, Integer> {
 
     Optional<AnchorEntity> findByDataspaceAndName(@NotNull DataspaceEntity dataspaceEntity, @NotNull String name);
diff --git a/integration-test/pom.xml b/integration-test/pom.xml
new file mode 100644 (file)
index 0000000..d6f55dd
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ============LICENSE_START=======================================================
+  Copyright (c) 2023 Nordix Foundation
+  ================================================================================
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  ============LICENSE_END=========================================================
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.onap.cps</groupId>
+        <artifactId>cps-parent</artifactId>
+        <version>3.2.1-SNAPSHOT</version>
+        <relativePath>../cps-parent/pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>integration-test</artifactId>
+
+<dependencies>
+    <dependency>
+        <groupId>org.onap.cps</groupId>
+        <artifactId>cps-ri</artifactId>
+    </dependency>
+    <dependency>
+        <groupId>org.onap.cps</groupId>
+        <artifactId>cps-service</artifactId>
+    </dependency>
+    <!-- T E S T   D E P E N D E N C I E S -->
+    <dependency>
+        <groupId>org.codehaus.groovy</groupId>
+        <artifactId>groovy</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.spockframework</groupId>
+        <artifactId>spock-core</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.spockframework</groupId>
+        <artifactId>spock-spring</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-test</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.testcontainers</groupId>
+        <artifactId>postgresql</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.testcontainers</groupId>
+        <artifactId>spock</artifactId>
+        <scope>test</scope>
+    </dependency>
+    <dependency>
+        <groupId>org.springframework.kafka</groupId>
+        <artifactId>spring-kafka-test</artifactId>
+        <scope>test</scope>
+    </dependency>
+</dependencies>
+</project>
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/CpsIntegrationSpecBase.groovy
new file mode 100644 (file)
index 0000000..9604832
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the 'License');
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an 'AS IS' BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration
+
+import org.onap.cps.api.impl.CpsAdminServiceImpl
+import org.onap.cps.api.impl.CpsDataServiceImpl
+import org.onap.cps.api.impl.CpsModuleServiceImpl
+import org.onap.cps.spi.CascadeDeleteAllowed
+import org.onap.cps.spi.repository.DataspaceRepository
+import org.onap.cps.spi.impl.utils.CpsValidatorImpl
+import org.onap.cps.utils.ContentType
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration
+import org.springframework.boot.autoconfigure.domain.EntityScan
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.context.annotation.ComponentScan
+import org.springframework.context.annotation.Lazy
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories
+import org.testcontainers.spock.Testcontainers
+import spock.lang.Shared
+import spock.lang.Specification
+
+import java.time.OffsetDateTime
+
+@SpringBootTest(classes = [TestConfig, CpsAdminServiceImpl, CpsValidatorImpl])
+@Testcontainers
+@EnableAutoConfiguration
+@EnableJpaRepositories(basePackageClasses = [DataspaceRepository])
+@ComponentScan(basePackages = ["org.onap.cps.api", "org.onap.cps.spi.repository"])
+@EntityScan("org.onap.cps.spi.entities")
+class CpsIntegrationSpecBase extends Specification {
+
+    @Shared
+    DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance()
+
+    @Autowired
+    @Lazy
+    CpsAdminServiceImpl cpsAdminService
+
+    @Autowired
+    @Lazy
+    CpsDataServiceImpl cpsDataService
+
+    @Autowired
+    @Lazy
+    CpsModuleServiceImpl cpsModuleService
+
+
+    def static TEST_DATASPACE = 'testDataspace'
+    def static BOOKSTORE_SCHEMA_SET = 'bookstoreSchemaSet'
+    def static TEST_ANCHOR = 'testAnchor'
+
+    def createDataspaceSchemaSetAnchor(String dataspaceName, String schemaSetName, String schemaSetFileName, String anchorName) {
+        cpsAdminService.createDataspace(dataspaceName)
+        createSchemaSetAnchor(dataspaceName, schemaSetName, schemaSetFileName, anchorName)
+    }
+
+    def createSchemaSetAnchor(String dataspaceName, String schemaSetName, String schemaSetFileName, String anchorName) {
+        def bookstoreFileContent = readResourceFile(schemaSetFileName)
+        cpsModuleService.createSchemaSet(dataspaceName, schemaSetName, [(schemaSetFileName) : bookstoreFileContent])
+        cpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName)
+    }
+
+    def saveDataNodes(String dataspaceName, String anchorName, String parentNodeXpath, String dataNodesFileName) {
+        def dataNodesAsJSON = readResourceFile(dataNodesFileName)
+        if (isRootXpath(parentNodeXpath)) {
+            cpsDataService.saveData(dataspaceName, anchorName, dataNodesAsJSON,
+                OffsetDateTime.now(), ContentType.JSON);
+        } else {
+            cpsDataService.saveData(dataspaceName, anchorName, parentNodeXpath,
+                dataNodesAsJSON, OffsetDateTime.now(), ContentType.JSON);
+        }
+    }
+
+    def deleteAllFromTestDataspace() {
+        def anchors = cpsAdminService.getAnchors(TEST_DATASPACE)
+        for(anchor in anchors) {
+            cpsDataService.deleteDataNodes(TEST_DATASPACE, anchor.getName(), OffsetDateTime.now())
+            cpsAdminService.deleteAnchor(TEST_DATASPACE, anchor.getName())
+        }
+        def schemaSets = cpsModuleService.getSchemaSets(TEST_DATASPACE)
+        for(schemaSet in schemaSets) {
+            cpsModuleService.deleteSchemaSet(TEST_DATASPACE, schemaSet.getName(), CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
+        }
+    }
+
+    def static readResourceFile(String filename) {
+        return new File('src/test/resources/data/' + filename).text
+    }
+
+    def static isRootXpath(final String xpath) {
+        return "/".equals(xpath);
+    }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/CpsPersistenceSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/CpsPersistenceSpec.groovy
new file mode 100644 (file)
index 0000000..94bcb0a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the 'License');
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an 'AS IS' BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration
+
+import org.onap.cps.spi.FetchDescendantsOption
+
+class CpsPersistenceSpec extends CpsIntegrationSpecBase{
+
+    def 'Test creation of test data'() {
+        when: 'A dataspace, schema set and anchor are persisted'
+            createDataspaceSchemaSetAnchor(TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'bookstore.yang', TEST_ANCHOR)
+        and: 'data nodes are persisted under the created anchor'
+            saveDataNodes(TEST_DATASPACE, TEST_ANCHOR, '/', 'BookstoreDataNodes.json')
+        then: 'The dataspace has been persisted successfully'
+            cpsAdminService.getDataspace(TEST_DATASPACE).getName() == TEST_DATASPACE
+        and: 'The schema set has been persisted successfully'
+            cpsModuleService.getSchemaSet(TEST_DATASPACE, BOOKSTORE_SCHEMA_SET).getName() == BOOKSTORE_SCHEMA_SET
+        and: 'The anchor has been persisted successfully'
+            cpsAdminService.getAnchor(TEST_DATASPACE, TEST_ANCHOR).getName() == TEST_ANCHOR
+        and: 'The data nodes have been persisted successfully'
+            cpsDataService.getDataNode(TEST_DATASPACE, TEST_ANCHOR, '/bookstore', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS).xpath == '/bookstore'
+    }
+
+    def 'Test deletion of all test data'() {
+        when: 'delete all from test dataspace method is called'
+            deleteAllFromTestDataspace()
+        and: 'the test dataspace is deleted'
+            cpsAdminService.deleteDataspace(TEST_DATASPACE)
+        then: 'there is no test dataspace'
+            !cpsAdminService.getAllDataspaces().contains(TEST_DATASPACE)
+    }
+
+    def 'Read test for persisted data nodes'() {
+        given:'There is a test dataspace created'
+            cpsAdminService.createDataspace(TEST_DATASPACE)
+        and: 'There is a schema set and anchor for the test dataspace'
+            createSchemaSetAnchor(TEST_DATASPACE, 'bookstoreSchemaSet', 'bookstore.yang', TEST_ANCHOR)
+        when: 'data is persisted to the database'
+            saveDataNodes(TEST_DATASPACE, TEST_ANCHOR, "/", "BookstoreDataNodes.json")
+        then: 'the correct data is saved'
+            cpsDataService.getDataNode(TEST_DATASPACE, TEST_ANCHOR, '/bookstore', FetchDescendantsOption.OMIT_DESCENDANTS).leaves['bookstore-name'] == 'Easons'
+    }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/TestConfig.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/TestConfig.groovy
new file mode 100644 (file)
index 0000000..273d7bb
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the 'License');
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an 'AS IS' BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.notification.NotificationService
+import org.onap.cps.spi.CpsDataPersistenceService
+import org.onap.cps.spi.CpsModulePersistenceService
+import org.onap.cps.spi.impl.CpsAdminPersistenceServiceImpl
+import org.onap.cps.spi.impl.CpsDataPersistenceServiceImpl
+import org.onap.cps.spi.impl.CpsModulePersistenceServiceImpl
+import org.onap.cps.spi.repository.AnchorRepository
+import org.onap.cps.spi.repository.DataspaceRepository
+import org.onap.cps.spi.repository.FragmentRepository
+import org.onap.cps.spi.repository.ModuleReferenceRepository
+import org.onap.cps.spi.repository.SchemaSetRepository
+import org.onap.cps.spi.repository.YangResourceRepository
+import org.onap.cps.spi.utils.SessionManager
+import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.context.annotation.Bean
+import org.springframework.context.annotation.Configuration
+import org.springframework.context.annotation.Lazy
+import spock.lang.Specification
+
+@Configuration
+class TestConfig extends Specification{
+    @Autowired
+    @Lazy
+    DataspaceRepository dataspaceRepository
+
+    @Autowired
+    @Lazy
+    AnchorRepository anchorRepository
+
+    @Autowired
+    @Lazy
+    SchemaSetRepository schemaSetRepository
+
+    @Autowired
+    @Lazy
+    YangResourceRepository yangResourceRepository
+
+    @Autowired
+    @Lazy
+    FragmentRepository fragmentRepository
+
+    @Autowired
+    @Lazy
+    ModuleReferenceRepository moduleReferenceRepository
+
+    @Autowired
+    @Lazy
+    JsonObjectMapper jsonObjectMapper
+
+    @Autowired
+    @Lazy
+    NotificationService stubbedNotificationService
+
+    @Autowired
+    @Lazy
+    SessionManager stubbedSessionManager
+
+    @Bean
+    CpsAdminPersistenceServiceImpl cpsAdminPersistenceService() {
+        new CpsAdminPersistenceServiceImpl(dataspaceRepository, anchorRepository, schemaSetRepository, yangResourceRepository)
+    }
+
+    @Bean
+    CpsDataPersistenceService cpsDataPersistenceService() {
+        return (CpsDataPersistenceService) new CpsDataPersistenceServiceImpl(dataspaceRepository, anchorRepository, fragmentRepository, jsonObjectMapper, stubbedSessionManager)
+    }
+
+    @Bean
+    CpsModulePersistenceService cpsModulePersistenceService() {
+        return (CpsModulePersistenceService) new CpsModulePersistenceServiceImpl(yangResourceRepository, schemaSetRepository, dataspaceRepository, cpsAdminPersistenceService(), moduleReferenceRepository)
+    }
+
+    @Bean
+    JsonObjectMapper jsonObjectMapper() {
+        return new JsonObjectMapper(new ObjectMapper())
+    }
+
+    @Bean
+    NotificationService notificationService() {
+        return Stub(NotificationService)
+    }
+
+    @Bean
+    SessionManager sessionManager() {
+        return Stub(SessionManager)
+    }
+}
\ No newline at end of file
diff --git a/integration-test/src/test/java/org/onap/cps/integration/DatabaseTestContainer.java b/integration-test/src/test/java/org/onap/cps/integration/DatabaseTestContainer.java
new file mode 100644 (file)
index 0000000..acf94b7
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ *  ============LICENSE_START=======================================================
+ *  Copyright (C) 2023 Nordix Foundation.
+ *  ================================================================================
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ *  SPDX-License-Identifier: Apache-2.0
+ *  ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.integration;
+
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testcontainers.utility.DockerImageName;
+
+/**
+ * The Postgresql database test container wrapper.
+ * Singleton implementation allows saving time on database initialization which otherwise would occur on each test.
+ * for debugging/developing purposes you can suspend any test and connect to this database:
+ *  docker exec -it {container-id} sh
+ *  psql -d test -U test
+ */
+public class DatabaseTestContainer extends PostgreSQLContainer<DatabaseTestContainer> {
+    private static final String IMAGE_VERSION = "registry.nordix.org/onaptest/postgres:14.1";
+    private static DatabaseTestContainer databaseTestContainer;
+
+    private DatabaseTestContainer() {
+        super(DockerImageName.parse(IMAGE_VERSION).asCompatibleSubstituteFor("postgres"));
+    }
+
+    /**
+     * Provides an instance of test container wrapper.
+     * The returned value expected to be assigned to static variable annotated with @ClassRule.
+     * This will allow to initialize DB connection env variables before DataSource object
+     * is initialized by Spring framework.
+     *
+     */
+    public static DatabaseTestContainer getInstance() {
+        if (databaseTestContainer == null) {
+            databaseTestContainer = new DatabaseTestContainer();
+            Runtime.getRuntime().addShutdownHook(new Thread(databaseTestContainer::terminate));
+        }
+        return databaseTestContainer;
+    }
+
+    @Override
+    public void start() {
+        super.start();
+        System.setProperty("DB_URL", databaseTestContainer.getJdbcUrl());
+        System.setProperty("DB_USERNAME", databaseTestContainer.getUsername());
+        System.setProperty("DB_PASSWORD", databaseTestContainer.getPassword());
+    }
+
+    @Override
+    public void stop() {
+        // do nothing on test completion, image removal will be performed via terminate() on JVM shutdown
+    }
+
+    private void terminate() {
+        super.stop();
+    }
+}
diff --git a/integration-test/src/test/resources/application.yml b/integration-test/src/test/resources/application.yml
new file mode 100644 (file)
index 0000000..0aefac8
--- /dev/null
@@ -0,0 +1,37 @@
+# ============LICENSE_START=======================================================
+# Copyright (C) 2023 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+#  SPDX-License-Identifier: Apache-2.0
+#  ============LICENSE_END=========================================================
+
+spring:
+  jpa:
+    ddl-auto: create
+    show-sql: false
+    properties:
+      hibernate:
+        enable_lazy_load_no_trans: true
+        dialect: org.hibernate.dialect.PostgreSQLDialect
+        format_sql: true
+        show_sql: false
+
+  datasource:
+    url: ${DB_URL}
+    username: ${DB_USERNAME}
+    password: ${DB_PASSWORD}
+    driverClassName: org.postgresql.Driver
+    initialization-mode: always
+
+  liquibase:
+    change-log: classpath:liquibase/test-changelog.yaml
diff --git a/integration-test/src/test/resources/data/BookstoreDataNodes.json b/integration-test/src/test/resources/data/BookstoreDataNodes.json
new file mode 100644 (file)
index 0000000..1c6cb88
--- /dev/null
@@ -0,0 +1,54 @@
+{
+  "bookstore": {
+    "bookstore-name": "Easons",
+    "categories": [
+      {
+        "code": 1,
+        "name": "Children",
+        "books" : [
+          {
+            "title": "Matilda",
+            "lang": "English",
+            "authors": ["Roald Dahl"],
+            "pub_year": 1988,
+            "price": 10
+          },
+          {
+            "title": "The Gruffalo",
+            "lang": "English",
+            "authors": ["Julia Donaldson"],
+            "pub_year": 1999,
+            "price": 15
+          }
+        ]
+      },
+      {
+        "code": 2,
+        "name": "Thriller",
+        "books" : [
+          {
+            "title": "Annihilation",
+            "lang": "English",
+            "authors": ["Jeff VanderMeer"],
+            "pub_year": 2014,
+            "price": 15
+          }
+        ]
+      },
+      {
+        "code": 3,
+        "name": "Comedy",
+        "books" : [
+          {
+            "title": "Good Omens",
+            "lang": "English",
+            "authors": ["Neil Gaiman", "Terry Pratchett"],
+            "pub_year": 2006,
+            "price": 13
+          }
+        ]
+      }
+
+    ]
+  }
+}
\ No newline at end of file
diff --git a/integration-test/src/test/resources/data/bookstore.yang b/integration-test/src/test/resources/data/bookstore.yang
new file mode 100644 (file)
index 0000000..2179fb9
--- /dev/null
@@ -0,0 +1,57 @@
+module stores {
+    yang-version 1.1;
+    namespace "org:onap:ccsdk:sample";
+
+    prefix book-store;
+
+    revision "2020-09-15" {
+        description
+        "Sample Model";
+    }
+
+    typedef year {
+        type uint16 {
+            range "1000..9999";
+        }
+    }
+
+    container bookstore {
+
+        leaf bookstore-name {
+            type string;
+        }
+
+    list categories {
+
+        key "code";
+
+        leaf code {
+            type string;
+        }
+
+        leaf name {
+            type string;
+        }
+
+        list books {
+            key title;
+
+            leaf title {
+                type string;
+            }
+            leaf lang {
+                type string;
+            }
+            leaf-list authors {
+                type string;
+            }
+            leaf pub_year {
+                type year;
+            }
+            leaf price {
+                type uint64;
+            }
+        }
+    }
+    }
+}
diff --git a/integration-test/src/test/resources/hibernate.cfg.xml b/integration-test/src/test/resources/hibernate.cfg.xml
new file mode 100644 (file)
index 0000000..513c00a
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE hibernate-configuration PUBLIC
+        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
+        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
+
+<hibernate-configuration>
+    <session-factory>
+        <property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
+        <property name="hibernate.connection.url">${DB_URL}</property>
+        <property name="hibernate.connection.username">${DB_USERNAME}</property>
+        <property name="hibernate.connection.password">${DB_PASSWORD}</property>
+        <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQL82Dialect</property>
+        <property name="show_sql">true</property>
+        <property name="hibernate.hbm2ddl.auto">none</property>
+    </session-factory>
+</hibernate-configuration>
\ No newline at end of file
diff --git a/integration-test/src/test/resources/liquibase/test-changelog.yaml b/integration-test/src/test/resources/liquibase/test-changelog.yaml
new file mode 100644 (file)
index 0000000..0c881b8
--- /dev/null
@@ -0,0 +1,615 @@
+# ============LICENSE_START=======================================================
+# Copyright (c) 2023 Nordix Foundation.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END=========================================================
+
+databaseChangeLog:
+  - changeSet:
+      id: 1-1
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: anchor_pkey
+                  name: id
+                  type: BIGINT
+              - column:
+                  name: name
+                  type: TEXT
+              - column:
+                  name: schema_set_id
+                  type: INTEGER
+              - column:
+                  constraints:
+                    nullable: false
+                  name: dataspace_id
+                  type: INTEGER
+            tableName: anchor
+  - changeSet:
+      id: 1-2
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  constraints:
+                    nullable: false
+                  name: from_fragment_id
+                  type: BIGINT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: to_fragment_id
+                  type: BIGINT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: relation_type_id
+                  type: INTEGER
+              - column:
+                  constraints:
+                    nullable: false
+                  name: from_rel_xpath
+                  type: TEXT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: to_rel_xpath
+                  type: TEXT
+            tableName: relation
+  - changeSet:
+      id: 1-3
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  constraints:
+                    nullable: false
+                  name: relation_type
+                  type: TEXT
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: relation_type_pkey
+                  name: id
+                  type: INTEGER
+            tableName: relation_type
+  - changeSet:
+      id: 1-4
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: fragment_pkey
+                  name: id
+                  type: BIGINT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: xpath
+                  type: TEXT
+              - column:
+                  name: attributes
+                  type: JSONB
+              - column:
+                  name: anchor_id
+                  type: BIGINT
+              - column:
+                  name: parent_id
+                  type: BIGINT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: dataspace_id
+                  type: INTEGER
+              - column:
+                  name: schema_node_id
+                  type: INTEGER
+            tableName: fragment
+  - changeSet:
+      id: 1-5
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: schema_set_pkey
+                  name: id
+                  type: INTEGER
+              - column:
+                  constraints:
+                    nullable: false
+                  name: name
+                  type: TEXT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: dataspace_id
+                  type: BIGINT
+            tableName: schema_set
+  - changeSet:
+      id: 1-6
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: yang_resource_pkey
+                  name: id
+                  type: INTEGER
+              - column:
+                  constraints:
+                    nullable: false
+                  name: name
+                  type: TEXT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: content
+                  type: TEXT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: checksum
+                  type: TEXT
+            tableName: yang_resource
+  - changeSet:
+      id: 1-7
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: dataspace_pkey
+                  name: id
+                  type: INTEGER
+              - column:
+                  constraints:
+                    nullable: false
+                  name: name
+                  type: TEXT
+            tableName: dataspace
+  - changeSet:
+      id: 1-8
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  constraints:
+                    nullable: false
+                  name: schema_node_identifier
+                  type: TEXT
+              - column:
+                  autoIncrement: true
+                  constraints:
+                    nullable: false
+                    primaryKey: true
+                    primaryKeyName: schema_node_pkey
+                  name: id
+                  type: INTEGER
+            tableName: schema_node
+  - changeSet:
+      id: 1-9
+      author: cps
+      changes:
+        - createTable:
+            columns:
+              - column:
+                  constraints:
+                    nullable: false
+                  name: schema_set_id
+                  type: BIGINT
+              - column:
+                  constraints:
+                    nullable: false
+                  name: yang_resource_id
+                  type: BIGINT
+            tableName: schema_set_yang_resources
+  - changeSet:
+      id: 1-10
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: schema_set_id
+            indexName: FKI_ANCHOR_SCHEMA_SET_ID_FK
+            tableName: anchor
+  - changeSet:
+      id: 1-11
+      author: cps
+      changes:
+        - addUniqueConstraint:
+            columnNames: dataspace_id, name
+            constraintName: anchor_dataspace_id_name_key
+            tableName: anchor
+  - changeSet:
+      id: 1-12
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: anchor_id
+            baseTableName: fragment
+            constraintName: fragment_anchor_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: anchor
+            validate: true
+  - changeSet:
+      id: 1-13
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: from_fragment_id
+            indexName: FKI_RELATIONS_FROM_ID_FK
+            tableName: relation
+  - changeSet:
+      id: 1-14
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: to_fragment_id
+            indexName: FKI_RELATIONS_TO_ID_FK
+            tableName: relation
+  - changeSet:
+      id: 1-15
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: relation_type_id
+            indexName: FKI_RELATION_TYPE_ID_FK
+            tableName: relation
+  - changeSet:
+      id: 1-16
+      author: cps
+      changes:
+        - addPrimaryKey:
+            columnNames: to_fragment_id, from_fragment_id, relation_type_id
+            constraintName: relation_pkey
+            tableName: relation
+  - changeSet:
+      id: 1-17
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: anchor_id
+            indexName: FKI_FRAGMENT_ANCHOR_ID_FK
+            tableName: fragment
+  - changeSet:
+      id: 1-18
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: dataspace_id
+            indexName: FKI_FRAGMENT_DATASPACE_ID_FK
+            tableName: fragment
+  - changeSet:
+      id: 1-19
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: parent_id
+            indexName: FKI_FRAGMENT_PARENT_ID_FK
+            tableName: fragment
+  - changeSet:
+      id: 1-20
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: schema_node_id
+            indexName: FKI_SCHEMA_NODE_ID_TO_ID
+            tableName: fragment
+  - changeSet:
+      id: 1-21
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: xpath
+              - column:
+                  name: dataspace_id
+            indexName: UQ_FRAGMENT_XPATH
+            tableName: fragment
+            unique: true
+  - changeSet:
+      id: 1-22
+      author: cps
+      changes:
+        - addUniqueConstraint:
+            columnNames: dataspace_id, anchor_id, xpath
+            constraintName: fragment_dataspace_id_anchor_id_xpath_key
+            tableName: fragment
+  - changeSet:
+      id: 1-23
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: from_fragment_id
+            baseTableName: relation
+            constraintName: relation_from_fragment_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: fragment
+            validate: true
+  - changeSet:
+      id: 1-24
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: to_fragment_id
+            baseTableName: relation
+            constraintName: relation_to_fragment_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: fragment
+            validate: true
+  - changeSet:
+      id: 1-25
+      author: cps
+      changes:
+        - addUniqueConstraint:
+            columnNames: name, dataspace_id
+            constraintName: schema_set_name_dataspace_id_key
+            tableName: schema_set
+  - changeSet:
+      id: 1-26
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: schema_set_id
+            baseTableName: schema_set_yang_resources
+            constraintName: schema_set_resource
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: CASCADE
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: schema_set
+            validate: true
+  - changeSet:
+      id: 1-27
+      author: cps
+      changes:
+        - addUniqueConstraint:
+            columnNames: checksum
+            constraintName: yang_resource_checksum_key
+            tableName: yang_resource
+  - changeSet:
+      id: 1-28
+      author: cps
+      changes:
+        - addUniqueConstraint:
+            columnNames: name
+            constraintName: UQ_NAME
+            tableName: dataspace
+  - changeSet:
+      id: 1-29
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: dataspace_id
+            baseTableName: fragment
+            constraintName: fragment_dataspace_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: dataspace
+            validate: true
+  - changeSet:
+      id: 1-30
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: dataspace_id
+            baseTableName: schema_set
+            constraintName: schema_set_dataspace
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: CASCADE
+            onUpdate: CASCADE
+            referencedColumnNames: id
+            referencedTableName: dataspace
+            validate: true
+  - changeSet:
+      id: 1-31
+      author: cps
+      changes:
+        - createIndex:
+            columns:
+              - column:
+                  name: schema_node_identifier
+            indexName: PERF_SCHEMA_NODE_SCHEMA_NODE_ID
+            tableName: schema_node
+  - changeSet:
+      id: 1-32
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: yang_resource_id
+            baseTableName: schema_set_yang_resources
+            constraintName: schema_set_yang_resources_yang_resource_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: yang_resource
+            validate: true
+  - changeSet:
+      id: 1-33
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: dataspace_id
+            baseTableName: anchor
+            constraintName: anchor_dataspace_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: dataspace
+            validate: true
+  - changeSet:
+      id: 1-34
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: schema_set_id
+            baseTableName: anchor
+            constraintName: anchor_schema_set_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: schema_set
+            validate: true
+  - changeSet:
+      id: 1-35
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: relation_type_id
+            baseTableName: relation
+            constraintName: relation_relation_type_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: relation_type
+            validate: true
+  - changeSet:
+      id: 1-36
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: parent_id
+            baseTableName: fragment
+            constraintName: fragment_parent_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: fragment
+            validate: true
+  - changeSet:
+      id: 1-37
+      author: cps
+      changes:
+        - addForeignKeyConstraint:
+            baseColumnNames: schema_node_id
+            baseTableName: fragment
+            constraintName: fragment_schema_node_id_fkey
+            deferrable: false
+            initiallyDeferred: false
+            onDelete: NO ACTION
+            onUpdate: NO ACTION
+            referencedColumnNames: id
+            referencedTableName: schema_node
+            validate: true
+
+
+  - changeSet:
+      id: 1-38
+      label: add-module-name-and-revision-column
+      author: cps
+      changes:
+        - addColumn:
+            tableName: yang_resource
+            columns:
+              - column:
+                  name: module_name
+                  type: TEXT
+              - column:
+                  name: revision
+                  type: TEXT
+
+  - changeSet:
+      id: 1-39
+      label: update-previous-data-module-name-and-revision
+      author: cps
+      changes:
+        - sql:
+            sql: update yang_resource set module_name = 'dummy_module_name', revision = '2021-08-04' where module_name is null and revision is null
+      rollback:
+        sql: update yang_resource set module_name = null, revision = null where module_name = 'dummy_module_name' and revision = '2021-08-04'
+
+  - changeSet:
+      author: cps
+      label: yang-resource-rename-column
+      id: 1-40
+      changes:
+        - renameColumn:
+            tableName: yang_resource
+            columnDataType: TEXT
+            oldColumnName: name
+            newColumnName: file_name
+      rollback:
+        - sql:
+            sql: alter table yang_resource rename column file_name to name
diff --git a/pom.xml b/pom.xml
index 501861c..ba1029a 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -2,7 +2,7 @@
 <!--\r
   ============LICENSE_START=======================================================\r
   Copyright (c) 2020 Linux Foundation.\r
-  Modifications Copyright (C) 2020-2021 Nordix Foundation\r
+  Modifications Copyright (C) 2020-2023 Nordix Foundation\r
   Modifications Copyright (C) 2020-2021 Pantheon.tech\r
   Modifications Copyright (C) 2021-2022 Bell Canada.\r
   ================================================================================\r
@@ -61,6 +61,7 @@
         <module>cps-ncmp-rest-stub</module>\r
         <module>cps-path-parser</module>\r
         <module>cps-ri</module>\r
+        <module>integration-test</module>\r
         <module>checkstyle</module>\r
         <module>spotbugs</module>\r
         <module>cps-application</module>\r