From 2806662125983758e3e3b5f4f8105745c539391b Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Wed, 27 Jan 2021 10:47:04 +0000 Subject: [PATCH] Introducing Spock/Groovy for Data Integration Tests Replaced CpsAdminPersistenceServiceTest with CpsAdminPersistenceServiceSpec Replaced CpsDataPersistenceServiceTest with CpsDataPersistenceServiceSpec Replaced CpsModulePersistenceServiceTest with CpsModulePersistenceServiceSpec Extracted out common integration test base Rationalised test (there was a lot of duplication already!) Issue-ID: CPS-160 Signed-off-by: ToineSiebelink Change-Id: I3311533fba1398feb00b6adf4209399cea8d3a1b --- cps-dependencies/pom.xml | 5 + cps-ri/pom.xml | 33 ++- .../spi/impl/CpsAdminPersistenceServiceSpec.groovy | 122 ++++++++++ .../spi/impl/CpsDataPersistenceServiceSpec.groovy | 150 ++++++++++++ .../impl/CpsModulePersistenceServiceSpec.groovy | 194 ++++++++++++++++ .../cps/spi/impl/CpsPersistenceSpecBase.groovy | 56 +++++ .../spi/impl/CpsAdminPersistenceServiceTest.java | 182 --------------- .../spi/impl/CpsDataPersistenceServiceTest.java | 200 ---------------- .../spi/impl/CpsModulePersistenceServiceTest.java | 251 --------------------- 9 files changed, 559 insertions(+), 634 deletions(-) create mode 100644 cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy create mode 100644 cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy create mode 100644 cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy create mode 100644 cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy delete mode 100755 cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java delete mode 100644 cps-ri/src/test/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceTest.java delete mode 100755 cps-ri/src/test/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceTest.java diff --git a/cps-dependencies/pom.xml b/cps-dependencies/pom.xml index 173686021..23683f65c 100755 --- a/cps-dependencies/pom.xml +++ b/cps-dependencies/pom.xml @@ -111,6 +111,11 @@ postgresql ${testcontainers.version} + + org.testcontainers + spock + ${testcontainers.version} + com.github.spotbugs spotbugs diff --git a/cps-ri/pom.xml b/cps-ri/pom.xml index 1805986c7..005fa272f 100644 --- a/cps-ri/pom.xml +++ b/cps-ri/pom.xml @@ -41,16 +41,47 @@ org.modelmapper modelmapper - + + + org.codehaus.groovy + groovy + test + + + org.spockframework + spock-core + test + + + org.spockframework + spock-spring + test + + + cglib + cglib-nodep + test + org.springframework.boot spring-boot-starter-test test + + + org.junit.vintage + junit-vintage-engine + + org.testcontainers postgresql test + + org.testcontainers + spock + test + diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy new file mode 100644 index 000000000..fd3e96481 --- /dev/null +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy @@ -0,0 +1,122 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.spi.impl + +import org.onap.cps.spi.CpsAdminPersistenceService +import org.onap.cps.spi.exceptions.AnchorAlreadyDefinedException +import org.onap.cps.spi.exceptions.AnchorNotFoundException +import org.onap.cps.spi.exceptions.DataspaceAlreadyDefinedException +import org.onap.cps.spi.exceptions.DataspaceNotFoundException +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException +import org.onap.cps.spi.model.Anchor +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.test.context.jdbc.Sql +import spock.lang.Unroll + +class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase { + + @Autowired + CpsAdminPersistenceService objectUnderTest + + static final String SET_DATA = '/data/anchor.sql' + static final String EMPTY_DATASPACE_NAME = 'DATASPACE-002' + + @Sql(CLEAR_DATA) + def 'Create and retrieve a new dataspace.'() { + when: 'a new dataspace is created' + def dataspaceName = 'some new dataspace' + objectUnderTest.createDataspace(dataspaceName) + then: 'that dataspace can be retrieved from the dataspace repository' + def dataspaceEntity = dataspaceRepository.findByName(dataspaceName).orElseThrow() + dataspaceEntity.id != null + dataspaceEntity.name == dataspaceName + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Attempt to create a duplicate dataspace.'() { + when: 'an attempt is made to create an already existing dataspace' + objectUnderTest.createDataspace(DATASPACE_NAME) + then: 'an exception that is is already defined is thrown with the correct details' + def thrown = thrown(DataspaceAlreadyDefinedException) + thrown.details.contains(DATASPACE_NAME) + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Create and retrieve a new anchor.'() { + when: 'a new anchor is created' + def newAnchorName = 'my new anchor' + objectUnderTest.createAnchor(DATASPACE_NAME, SCHEMA_SET_NAME1, newAnchorName) + then: 'that anchor can be retrieved' + def anchor = objectUnderTest.getAnchor(DATASPACE_NAME, newAnchorName) + anchor.name == newAnchorName + anchor.dataspaceName == DATASPACE_NAME + anchor.schemaSetName == SCHEMA_SET_NAME1 + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Create anchor error scenario: #scenario.'() { + when: 'attempt to create new anchor named #anchorName in dataspace #dataspaceName with #schemaSetName' + objectUnderTest.createAnchor(dataspaceName, schemaSetName, anchorName) + then: 'an #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | schemaSetName | anchorName || expectedException + 'dataspace does not exist' | 'unknown' | 'not-relevant' | 'not-relevant' || DataspaceNotFoundException + 'schema set does not exist' | DATASPACE_NAME | 'unknown' | 'not-relevant' || SchemaSetNotFoundException + 'anchor already exists' | DATASPACE_NAME | SCHEMA_SET_NAME1 | ANCHOR_NAME1 || AnchorAlreadyDefinedException + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Get anchor error scenario: #scenario.'() { + when: 'attempt to get anchor named #anchorName in dataspace #dataspaceName' + objectUnderTest.getAnchor(dataspaceName, anchorName) + then: 'an #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | anchorName || expectedException + 'dataspace does not exist' | 'unknown' | 'not-relevant' || DataspaceNotFoundException + 'anchor does not exists' | DATASPACE_NAME | 'unknown' || AnchorNotFoundException + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Get all anchors in dataspace #dataspaceName.'() { + when: 'all anchors are retrieved from #DATASPACE_NAME' + def result = objectUnderTest.getAnchors(dataspaceName) + then: 'the expected collection of anchors is returned' + result.size() == expectedAnchors.size() + result.containsAll(expectedAnchors) + where: 'the following data is used' + dataspaceName || expectedAnchors + DATASPACE_NAME || [Anchor.builder().name(ANCHOR_NAME1).schemaSetName(SCHEMA_SET_NAME1).dataspaceName(DATASPACE_NAME).build(), + Anchor.builder().name(ANCHOR_NAME2).schemaSetName(SCHEMA_SET_NAME2).dataspaceName(DATASPACE_NAME).build()] + EMPTY_DATASPACE_NAME || [] + } + + @Sql(CLEAR_DATA) + def 'Get all anchors in unknown dataspace.'() { + when: 'attempt to get all anchors in an unknown dataspace' + objectUnderTest.getAnchors('unknown dataspace') + then: 'an DataspaceNotFoundException is thrown' + thrown(DataspaceNotFoundException) + } +} diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy new file mode 100644 index 000000000..03e352a87 --- /dev/null +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy @@ -0,0 +1,150 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.spi.impl + +import com.google.common.collect.ImmutableSet +import org.onap.cps.spi.CpsDataPersistenceService +import org.onap.cps.spi.exceptions.AnchorNotFoundException +import org.onap.cps.spi.exceptions.DataNodeNotFoundException +import org.onap.cps.spi.exceptions.DataspaceNotFoundException +import org.onap.cps.spi.model.DataNode +import org.onap.cps.spi.model.DataNodeBuilder +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.dao.DataIntegrityViolationException +import org.springframework.test.context.jdbc.Sql + +class CpsDataPersistenceServiceSpec extends CpsPersistenceSpecBase { + + @Autowired + CpsDataPersistenceService objectUnderTest + + static final String SET_DATA = '/data/fragment.sql' + static final long ID_DATA_NODE_WITH_DESCENDANTS = 4001 + static final String XPATH_DATA_NODE_WITH_DESCENDANTS = '/parent-1' + + static final DataNode newDataNode = new DataNodeBuilder().build() + static DataNode existingDataNode + static DataNode existingChildDataNode + + static { + existingDataNode = createDataNodeTree(XPATH_DATA_NODE_WITH_DESCENDANTS) + existingChildDataNode = createDataNodeTree('/parent-1/child-1') + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Get fragment with descendants.'() { + /* + TODO: This test is not really testing the object under test! Needs to be updated as part of CPS-71 + Actually I think this test will become redundant once th store data node tests is asserted using + a new getByXpath() method in the service (object under test) + A lot of preloaded dat will become redundant then too + */ + // + when: 'a fragment is retrieved from the repository' + def fragment = fragmentRepository.findById(ID_DATA_NODE_WITH_DESCENDANTS).orElseThrow() + then: 'it has the correct xpath' + fragment.xpath == '/parent-1' + and: 'it contains the children' + fragment.childFragments.size() == 1 + def childFragment = fragment.childFragments[0] + childFragment.xpath == '/parent-1/child-1' + and: "and its children's children" + childFragment.childFragments.size() == 1 + def grandchildFragment = childFragment.childFragments[0] + grandchildFragment.xpath == '/parent-1/child-1/grandchild-1' + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'StoreDataNode with descendants.'() { + when: 'a fragment with descendants is stored' + def parentXpath = "/parent-new" + def childXpath = "/parent-new/child-new" + def grandChildXpath = "/parent-new/child-new/grandchild-new" + objectUnderTest.storeDataNode(DATASPACE_NAME, ANCHOR_NAME1, + createDataNodeTree(parentXpath, childXpath, grandChildXpath)) + then: 'it can be retrieved by its xpath' + def parentFragment = getFragmentByXpath(parentXpath) + and: 'it contains the children' + parentFragment.childFragments.size() == 1 + def childFragment = parentFragment.childFragments[0] + childFragment.xpath == childXpath + and: "and its children's children" + childFragment.childFragments.size() == 1 + def grandchildFragment = childFragment.childFragments[0] + grandchildFragment.xpath == grandChildXpath + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Store datanode error scenario: #scenario.'() { + when: 'attempt to store a data node with #scenario' + objectUnderTest.storeDataNode(dataspaceName, anchorName, dataNode) + then: 'a #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | anchorName | dataNode || expectedException + 'dataspace does not exist' | 'unknown' | 'not-relevant' | newDataNode || DataspaceNotFoundException + 'schema set does not exist' | DATASPACE_NAME | 'unknown' | newDataNode || AnchorNotFoundException + 'anchor already exists' | DATASPACE_NAME | ANCHOR_NAME1 | existingDataNode || DataIntegrityViolationException + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Add a child to a Fragment that already has a child.'() { + given: ' a new child node' + def newChild = createDataNodeTree('xpath for new child') + when: 'the child is added to an existing parent with 1 child' + objectUnderTest.addChildDataNode(DATASPACE_NAME, ANCHOR_NAME1, XPATH_DATA_NODE_WITH_DESCENDANTS, newChild) + then: 'the parent is now has to 2 children' + def expectedExistingChildPath = '/parent-1/child-1' + def parentFragment = fragmentRepository.findById(ID_DATA_NODE_WITH_DESCENDANTS).orElseThrow() + parentFragment.getChildFragments().size() == 2 + and : 'it still has the old child' + parentFragment.getChildFragments().find( {it.xpath == expectedExistingChildPath}) + and : 'it has the new child' + parentFragment.getChildFragments().find( {it.xpath == newChild.xpath}) + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Add child error scenario: #scenario.'() { + when: 'attempt to add a child data node with #scenario' + objectUnderTest.addChildDataNode(DATASPACE_NAME, ANCHOR_NAME1, parentXpath, dataNode) + then: 'a #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | parentXpath | dataNode || expectedException + 'parent does not exist' | 'unknown' | newDataNode || DataNodeNotFoundException + 'already existing child' | XPATH_DATA_NODE_WITH_DESCENDANTS | existingChildDataNode || DataIntegrityViolationException + } + + static def createDataNodeTree(String... xpaths) { + def dataNodeBuilder = new DataNodeBuilder().withXpath(xpaths[0]) + if (xpaths.length > 1) { + def xPathsDescendant = Arrays.copyOfRange(xpaths, 1, xpaths.length) + def childDataNode = createDataNodeTree(xPathsDescendant) + dataNodeBuilder.withChildDataNodes(ImmutableSet.of(childDataNode)) + } + dataNodeBuilder.build() + } + + def getFragmentByXpath = xpath -> { + //TODO: Remove this method when CPS-71 gets implemented + fragmentRepository.findAll().stream() + .filter(fragment -> fragment.getXpath().contains(xpath)).findAny().orElseThrow() + } + +} diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy new file mode 100644 index 000000000..b0c13af3d --- /dev/null +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsModulePersistenceServiceSpec.groovy @@ -0,0 +1,194 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.spi.impl + +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED +import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED + +import org.onap.cps.spi.CpsAdminPersistenceService +import org.onap.cps.spi.CpsModulePersistenceService +import org.onap.cps.spi.entities.YangResourceEntity +import org.onap.cps.spi.exceptions.DataspaceNotFoundException +import org.onap.cps.spi.exceptions.SchemaSetAlreadyDefinedException +import org.onap.cps.spi.exceptions.SchemaSetInUseException +import org.onap.cps.spi.exceptions.SchemaSetNotFoundException +import org.onap.cps.spi.repository.AnchorRepository +import org.onap.cps.spi.repository.SchemaSetRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.test.context.jdbc.Sql +import spock.lang.Unroll + +class CpsModulePersistenceServiceSpec extends CpsPersistenceSpecBase { + + @Autowired + CpsModulePersistenceService objectUnderTest + + @Autowired + AnchorRepository anchorRepository + + @Autowired + SchemaSetRepository schemaSetRepository + + @Autowired + CpsAdminPersistenceService cpsAdminPersistenceService + + static final String SET_DATA = '/data/schemaset.sql' + static final String EXISTING_SCHEMA_SET_NAME = SCHEMA_SET_NAME1 + static final String SCHEMA_SET_NAME_NO_ANCHORS = 'SCHEMA-SET-100' + static final String SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA = 'SCHEMA-SET-101' + static final String SCHEMA_SET_NAME_NEW = 'SCHEMA-SET-NEW' + + static final Long NEW_RESOURCE_ABSTRACT_ID = 0L + static final String NEW_RESOURCE_NAME = 'some new resource' + static final String NEW_RESOURCE_CONTENT = 'some resource content' + static final String NEW_RESOURCE_CHECKSUM = '8185b09f11e262f18043f0ea08803f46' + + def newYangResourcesNameToContentMap = [(NEW_RESOURCE_NAME):NEW_RESOURCE_CONTENT] + def dataspaceEntity + + def setup() { + dataspaceEntity = dataspaceRepository.getByName(DATASPACE_NAME) + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Store schema set error scenario: #scenario.'() { + when: 'attempt to store schema set #schemaSetName in dataspace #dataspaceName' + objectUnderTest.storeSchemaSet(dataspaceName, schemaSetName, newYangResourcesNameToContentMap) + then: 'an #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | schemaSetName || expectedException + 'dataspace does not exist' | 'unknown' | 'not-relevant' || DataspaceNotFoundException + 'schema set already exists' | DATASPACE_NAME | EXISTING_SCHEMA_SET_NAME || SchemaSetAlreadyDefinedException + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Store new schema set.'() { + when: 'a new schemaset is stored' + objectUnderTest.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, newYangResourcesNameToContentMap) + then: 'the schema set is persisted correctly' + assertSchemaSetPersisted(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, NEW_RESOURCE_ABSTRACT_ID, NEW_RESOURCE_NAME, + NEW_RESOURCE_CONTENT, NEW_RESOURCE_CHECKSUM) + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Retrieving schema set (resources) by anchor.'() { + given: 'a new schema set is stored' + objectUnderTest.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, newYangResourcesNameToContentMap) + and: 'an anchor is created with that schema set' + cpsAdminPersistenceService.createAnchor(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, ANCHOR_NAME1) + when: 'the schema set resources for that anchor is retrieved' + def result = objectUnderTest.getYangSchemaSetResources(DATASPACE_NAME, ANCHOR_NAME1) + then: 'the correct resources are returned' + result == newYangResourcesNameToContentMap + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Storing duplicate schema content.'() { + given: 'a new schema set with a resource with the same content as an existing resource' + def existingResourceContent = 'CONTENT-001' + def newYangResourcesNameToContentMap = [(NEW_RESOURCE_NAME):existingResourceContent] + when: 'the schema set with duplicate resource is stored' + objectUnderTest.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, newYangResourcesNameToContentMap) + then: 'the schema persisted (re)uses the existing id, name and has the same checksum' + def existingResourceId = 3001L + def existingResourceName = 'module1@2020-02-02.yang' + def existingResourceChecksum = '877e65a9f36d54e7702c3f073f6bc42b' + assertSchemaSetPersisted(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, + existingResourceId, existingResourceName, existingResourceContent, existingResourceChecksum) + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Delete schema set with cascade delete prohibited but no anchors using it'() { + when: 'a schema set is deleted with cascade-prohibited option' + objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS, + CASCADE_DELETE_PROHIBITED) + then: 'the schema set has been deleted' + schemaSetRepository.findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_NO_ANCHORS).isPresent() == false + and: 'any orphaned (not used by any schema set anymore) yang resources are deleted' + def orphanedResourceId = 3100L + yangResourceRepository.findById(orphanedResourceId).isPresent() == false + and: 'any shared (still in use by other schema set) yang resources still persists' + def sharedResourceId = 3003L + yangResourceRepository.findById(sharedResourceId).isPresent() + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Delete schema set with cascade allowed.'() { + when: 'a schema set is deleted with cascade-allowed option' + objectUnderTest.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA, + CASCADE_DELETE_ALLOWED) + then: 'the schema set has been deleted' + schemaSetRepository + .findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA).isPresent() == false + and: 'the associated anchors are removed' + def associatedAnchorsIds = [ 6001, 6002 ] + associatedAnchorsIds.each {anchorRepository.findById(it).isPresent() == false } + and: 'the fragment(s) under those anchors are removed' + def fragmentUnderAnchor1Id = 7001L + fragmentRepository.findById(fragmentUnderAnchor1Id).isPresent() == false + and: 'the shared resources still persist' + def sharedResourceIds = [ 3003L, 3004L ] + sharedResourceIds.each {yangResourceRepository.findById(it).isPresent() } + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Delete schema set error scenario: #scenario.'() { + when: 'attempt to delete a schema set where #scenario' + objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetName, CASCADE_DELETE_PROHIBITED) + then: 'an #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | schemaSetName || expectedException + 'dataspace does not exist' | 'unknown' | 'not-relevant' || DataspaceNotFoundException + 'schema set does not exists' | DATASPACE_NAME | 'unknown' || SchemaSetNotFoundException + 'cascade prohibited but schema set in use' | DATASPACE_NAME | SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA || SchemaSetInUseException + } + + def assertSchemaSetPersisted(expectedDataspaceName, + expectedSchemaSetName, + expectedYangResourceId, + expectedYangResourceName, + expectedYangResourceContent, + expectedYangResourceChecksum) { + // assert the schema set is persisted + def schemaSetEntity = schemaSetRepository + .findByDataspaceAndName(dataspaceEntity, expectedSchemaSetName).orElseThrow() + assert schemaSetEntity.name == expectedSchemaSetName + assert schemaSetEntity.dataspace.name == expectedDataspaceName + + // assert the attached yang resource is persisted + def yangResourceEntities = schemaSetEntity.getYangResources() + yangResourceEntities.size() == 1 + + // assert the attached yang resource content + YangResourceEntity yangResourceEntity = yangResourceEntities.iterator().next() + assert yangResourceEntity.id != null + if (expectedYangResourceId != NEW_RESOURCE_ABSTRACT_ID) { + // existing resource with known id + assert yangResourceEntity.id == expectedYangResourceId + } + yangResourceEntity.name == expectedYangResourceName + yangResourceEntity.content == expectedYangResourceContent + yangResourceEntity.checksum == expectedYangResourceChecksum + } + +} diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy new file mode 100644 index 000000000..54807efd2 --- /dev/null +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistenceSpecBase.groovy @@ -0,0 +1,56 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.spi.impl + +import org.onap.cps.DatabaseTestContainer +import org.onap.cps.spi.repository.DataspaceRepository +import org.onap.cps.spi.repository.FragmentRepository +import org.onap.cps.spi.repository.YangResourceRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.testcontainers.spock.Testcontainers +import spock.lang.Shared +import spock.lang.Specification + +@SpringBootTest +@Testcontainers +class CpsPersistenceSpecBase extends Specification { + + @Shared + DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance() + + @Autowired + DataspaceRepository dataspaceRepository + + @Autowired + YangResourceRepository yangResourceRepository + + @Autowired + FragmentRepository fragmentRepository + + static final String CLEAR_DATA = '/data/clear-all.sql' + + static final String DATASPACE_NAME = 'DATASPACE-001' + static final String SCHEMA_SET_NAME1 = 'SCHEMA-SET-001' + static final String SCHEMA_SET_NAME2 = 'SCHEMA-SET-002' + static final String ANCHOR_NAME1 = 'ANCHOR-001' + static final String ANCHOR_NAME2 = 'ANCHOR-002' + +} diff --git a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java b/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java deleted file mode 100755 index 981f06528..000000000 --- a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsAdminPersistenceServiceTest.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Pantheon.tech - * ================================================================================ - * 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.spi.impl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.Collection; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.onap.cps.DatabaseTestContainer; -import org.onap.cps.spi.CpsAdminPersistenceService; -import org.onap.cps.spi.entities.AnchorEntity; -import org.onap.cps.spi.entities.DataspaceEntity; -import org.onap.cps.spi.exceptions.AnchorAlreadyDefinedException; -import org.onap.cps.spi.exceptions.AnchorNotFoundException; -import org.onap.cps.spi.exceptions.DataspaceAlreadyDefinedException; -import org.onap.cps.spi.exceptions.DataspaceNotFoundException; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -import org.onap.cps.spi.model.Anchor; -import org.onap.cps.spi.repository.AnchorRepository; -import org.onap.cps.spi.repository.DataspaceRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.jdbc.Sql; -import org.springframework.test.context.jdbc.SqlGroup; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CpsAdminPersistenceServiceTest { - - private static final String CLEAR_DATA = "/data/clear-all.sql"; - private static final String SET_DATA = "/data/anchor.sql"; - - private static final String DATASPACE_NAME = "DATASPACE-001"; - private static final String EMPTY_DATASPACE_NAME = "DATASPACE-002"; - private static final String NON_EXISTING_DATASPACE_NAME = "NON EXISTING DATASPACE"; - private static final String NON_EXISTING_SCHEMA_SET_NAME = "NON EXISTING SCHEMA SET"; - private static final String SCHEMA_SET_NAME1 = "SCHEMA-SET-001"; - private static final String SCHEMA_SET_NAME2 = "SCHEMA-SET-002"; - private static final String ANCHOR_NAME1 = "ANCHOR-001"; - private static final String ANCHOR_NAME2 = "ANCHOR-002"; - private static final String ANCHOR_NAME_NEW = "ANCHOR-NEW"; - private static final String NON_EXISTING_ANCHOR_NAME = "NON EXISTING ANCHOR"; - - @ClassRule - public static DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance(); - - @Autowired - private CpsAdminPersistenceService cpsAdminPersistenceService; - - @Autowired - private AnchorRepository anchorRepository; - - @Autowired - private DataspaceRepository dataspaceRepository; - - @Test - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testCreateDataspace() { - final String dataspaceName = "DATASPACE-NEW"; - cpsAdminPersistenceService.createDataspace(dataspaceName); - - final DataspaceEntity dataspaceEntity = dataspaceRepository.findByName(dataspaceName).orElseThrow(); - assertNotNull(dataspaceEntity); - assertNotNull(dataspaceEntity.getId()); - assertEquals(dataspaceName, dataspaceEntity.getName()); - } - - @Test(expected = DataspaceAlreadyDefinedException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testCreateDataspaceWithNameAlreadyDefined() { - cpsAdminPersistenceService.createDataspace(DATASPACE_NAME); - } - - @Test - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testCreateAnchor() { - cpsAdminPersistenceService.createAnchor(DATASPACE_NAME, SCHEMA_SET_NAME2, ANCHOR_NAME_NEW); - - // validate anchor persisted - final DataspaceEntity dataspaceEntity = dataspaceRepository.findByName(DATASPACE_NAME).orElseThrow(); - final AnchorEntity anchorEntity = - anchorRepository.findByDataspaceAndName(dataspaceEntity, ANCHOR_NAME_NEW).orElseThrow(); - - assertNotNull(anchorEntity.getId()); - assertEquals(ANCHOR_NAME_NEW, anchorEntity.getName()); - assertEquals(DATASPACE_NAME, anchorEntity.getDataspace().getName()); - assertEquals(SCHEMA_SET_NAME2, anchorEntity.getSchemaSet().getName()); - } - - @Test(expected = DataspaceNotFoundException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testCreateAnchorAtNonExistingDataspace() { - cpsAdminPersistenceService.createAnchor(NON_EXISTING_DATASPACE_NAME, SCHEMA_SET_NAME2, ANCHOR_NAME_NEW); - } - - @Test(expected = SchemaSetNotFoundException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testCreateAnchorWithNonExistingSchemaSet() { - cpsAdminPersistenceService.createAnchor(DATASPACE_NAME, NON_EXISTING_SCHEMA_SET_NAME, ANCHOR_NAME_NEW); - } - - @Test(expected = AnchorAlreadyDefinedException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testCreateAnchorWithNameAlreadyDefined() { - cpsAdminPersistenceService.createAnchor(DATASPACE_NAME, SCHEMA_SET_NAME2, ANCHOR_NAME1); - } - - @Test - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testGetAnchorsByDataspace() { - final Collection anchors = cpsAdminPersistenceService.getAnchors(DATASPACE_NAME); - - assertNotNull(anchors); - assertEquals(2, anchors.size()); - assertTrue(anchors.contains( - Anchor.builder().name(ANCHOR_NAME1).schemaSetName(SCHEMA_SET_NAME1).dataspaceName(DATASPACE_NAME).build() - )); - assertTrue(anchors.contains( - Anchor.builder().name(ANCHOR_NAME2).schemaSetName(SCHEMA_SET_NAME2).dataspaceName(DATASPACE_NAME).build() - )); - } - - @Test(expected = DataspaceNotFoundException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testGetAnchorsByNonExistingDataspace() { - cpsAdminPersistenceService.getAnchors(NON_EXISTING_DATASPACE_NAME); - } - - @Test - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testGetAnchorsFromEmptyDataspace() { - final Collection anchors = cpsAdminPersistenceService.getAnchors(EMPTY_DATASPACE_NAME); - - assertNotNull(anchors); - assertTrue(anchors.isEmpty()); - } - - @Test - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testGetAnchorByDataspaceAndAnchorName() { - final Anchor anchor = cpsAdminPersistenceService.getAnchor(DATASPACE_NAME, ANCHOR_NAME1); - - assertNotNull(anchor); - assertEquals(ANCHOR_NAME1, anchor.getName()); - assertEquals(DATASPACE_NAME, anchor.getDataspaceName()); - } - - @Test(expected = DataspaceNotFoundException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testGetAnchorFromNonExistingDataspace() { - cpsAdminPersistenceService.getAnchor(NON_EXISTING_DATASPACE_NAME, ANCHOR_NAME1); - } - - @Test(expected = AnchorNotFoundException.class) - @SqlGroup({@Sql(CLEAR_DATA), @Sql(SET_DATA)}) - public void testGetAnchorByNonExistingAnchorName() { - cpsAdminPersistenceService.getAnchor(DATASPACE_NAME, NON_EXISTING_ANCHOR_NAME); - } - -} diff --git a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceTest.java b/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceTest.java deleted file mode 100644 index 5c402917d..000000000 --- a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceTest.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.spi.impl; - -import static junit.framework.TestCase.assertEquals; - -import com.google.common.collect.ImmutableSet; -import java.util.Arrays; -import org.assertj.core.api.Assertions; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.onap.cps.DatabaseTestContainer; -import org.onap.cps.spi.CpsDataPersistenceService; -import org.onap.cps.spi.entities.FragmentEntity; -import org.onap.cps.spi.exceptions.AnchorNotFoundException; -import org.onap.cps.spi.exceptions.DataNodeNotFoundException; -import org.onap.cps.spi.exceptions.DataspaceNotFoundException; -import org.onap.cps.spi.model.DataNode; -import org.onap.cps.spi.model.DataNodeBuilder; -import org.onap.cps.spi.repository.FragmentRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.dao.DataIntegrityViolationException; -import org.springframework.test.context.jdbc.Sql; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CpsDataPersistenceServiceTest { - - private static final String CLEAR_DATA = "/data/clear-all.sql"; - private static final String SET_DATA = "/data/fragment.sql"; - - private static final String DATASPACE_NAME = "DATASPACE-001"; - private static final String ANCHOR_NAME1 = "ANCHOR-001"; - - private static final long PARENT_ID_4001 = 4001; - private static final long PARENT_ID_4002 = 4002; - private static final long PARENT_ID_4003 = 4003; - private static final String PARENT_XPATH1 = "/parent-1"; - private static final String PARENT_XPATH2 = "/parent-2"; - private static final String PARENT_XPATH3 = "/parent-3"; - - private static final long CHILD_ID_4004 = 4004; - private static final String CHILD_XPATH1 = "/parent-1/child-1"; - private static final String CHILD_XPATH2 = "/parent-2/child-2"; - - private static final long GRAND_CHILD_ID_4006 = 4006; - private static final String GRAND_CHILD_XPATH1 = "/parent-1/child-1/grandchild-1"; - - @ClassRule - public static DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance(); - - @Autowired - private CpsDataPersistenceService cpsDataPersistenceService; - - @Autowired - private FragmentRepository fragmentRepository; - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testGetFragmentsWithChildAndGrandChild() { - final FragmentEntity parentFragment = fragmentRepository.findById(PARENT_ID_4001).orElseThrow(); - final FragmentEntity childFragment = fragmentRepository.findById(CHILD_ID_4004).orElseThrow(); - final FragmentEntity grandChildFragment = fragmentRepository.findById(GRAND_CHILD_ID_4006).orElseThrow(); - assertFragment(parentFragment, childFragment, grandChildFragment, PARENT_XPATH1, CHILD_XPATH1, - GRAND_CHILD_XPATH1); - } - - @Test(expected = DataspaceNotFoundException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreDataNodeAtNonExistingDataspace() { - cpsDataPersistenceService - .storeDataNode("Non Existing Dataspace Name", ANCHOR_NAME1, - new DataNodeBuilder().build()); - } - - @Test(expected = AnchorNotFoundException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreDataNodeAtNonExistingAnchor() { - cpsDataPersistenceService - .storeDataNode(DATASPACE_NAME, "Non Existing Anchor Name", - new DataNodeBuilder().build()); - } - - @Test(expected = DataIntegrityViolationException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreDataNodeWithIntegrityException() { - cpsDataPersistenceService.storeDataNode(DATASPACE_NAME, ANCHOR_NAME1, - createDataNodeTree(PARENT_XPATH1)); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreDataNodeWithChildAndGrandChild() { - final String parentXpath = "/parent-new"; - final String childXpath = "/parent-new/child-new"; - final String grandChildXpath = "/parent-new/child-new/grandchild-new"; - - cpsDataPersistenceService.storeDataNode(DATASPACE_NAME, ANCHOR_NAME1, - createDataNodeTree(parentXpath, childXpath, grandChildXpath)); - final FragmentEntity parentFragment = getFragmentByXpath(parentXpath); - final FragmentEntity childFragment = getFragmentByXpath(childXpath); - final FragmentEntity grandChildFragment = getFragmentByXpath(grandChildXpath); - assertFragment(parentFragment, childFragment, grandChildFragment, parentXpath, childXpath, - grandChildXpath); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testAddChildToFragmentThatHasOneChild() { - final String childXpath = "some-xpath"; - final DataNode childDataNode = createDataNodeTree(childXpath); - cpsDataPersistenceService - .addChildDataNode(DATASPACE_NAME, ANCHOR_NAME1, PARENT_XPATH2, childDataNode); - final FragmentEntity parentFragment = fragmentRepository.findById(PARENT_ID_4002).orElseThrow(); - Assertions.assertThat(parentFragment.getChildFragments()) - .hasSize(2) - .extracting(FragmentEntity::getXpath) - .containsExactlyInAnyOrder(childXpath, CHILD_XPATH2); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testAddChildToFragmentThatHasNoChild() { - final String childXpath = "some-xpath"; - final DataNode childDataNode = createDataNodeTree(childXpath); - cpsDataPersistenceService - .addChildDataNode(DATASPACE_NAME, ANCHOR_NAME1, PARENT_XPATH3, childDataNode); - final FragmentEntity parentFragment = fragmentRepository.findById(PARENT_ID_4003).orElseThrow(); - Assertions.assertThat(parentFragment.getChildFragments()) - .hasSize(1) - .extracting(FragmentEntity::getXpath) - .containsExactlyInAnyOrder(childXpath); - } - - @Test(expected = DataIntegrityViolationException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testAddAChildWithTheSameXpathAsExistingChild() { - cpsDataPersistenceService - .addChildDataNode(DATASPACE_NAME, ANCHOR_NAME1, PARENT_XPATH1, createDataNodeTree(CHILD_XPATH1)); - } - - @Test(expected = DataNodeNotFoundException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testAddAChildWithToAParentThatDoesNotExist() { - cpsDataPersistenceService - .addChildDataNode(DATASPACE_NAME, ANCHOR_NAME1, "non-existing-xpath", createDataNodeTree("some-xpath")); - } - - private void assertFragment(final FragmentEntity parentFragment, final FragmentEntity childFragment, - final FragmentEntity grandChildFragment, final String parentXpath, final String childXpath, - final String grandChildXpath) { - assertEquals(parentXpath, parentFragment.getXpath()); - assertEquals(DATASPACE_NAME, parentFragment.getDataspace().getName()); - assertEquals(ANCHOR_NAME1, parentFragment.getAnchor().getName()); - - assertEquals(childXpath, childFragment.getXpath()); - assertEquals(DATASPACE_NAME, childFragment.getDataspace().getName()); - assertEquals(ANCHOR_NAME1, childFragment.getAnchor().getName()); - - assertEquals(grandChildXpath, grandChildFragment.getXpath()); - assertEquals(DATASPACE_NAME, grandChildFragment.getDataspace().getName()); - assertEquals(ANCHOR_NAME1, grandChildFragment.getAnchor().getName()); - } - - private FragmentEntity getFragmentByXpath(final String xpath) { - return fragmentRepository.findAll().stream() - .filter(fragment -> fragment.getXpath().contains(xpath)).findAny().orElseThrow(); - } - - private static DataNode createDataNodeTree(final String... xpaths) { - final DataNodeBuilder dataNodeBuilder = new DataNodeBuilder().withXpath(xpaths[0]); - if (xpaths.length > 1) { - final String[] xPathsDescendant = Arrays.copyOfRange(xpaths, 1, xpaths.length); - final DataNode childDataNode = createDataNodeTree(xPathsDescendant); - dataNodeBuilder.withChildDataNodes(ImmutableSet.of(childDataNode)); - - } - return dataNodeBuilder.build(); - } -} diff --git a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceTest.java b/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceTest.java deleted file mode 100755 index 0705fc4e6..000000000 --- a/cps-ri/src/test/java/org/onap/cps/spi/impl/CpsModulePersistenceServiceTest.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2020 Pantheon.tech - * ================================================================================ - * 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.spi.impl; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED; -import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED; - -import com.google.common.collect.ImmutableMap; -import java.util.Map; -import java.util.Set; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.onap.cps.DatabaseTestContainer; -import org.onap.cps.spi.CpsAdminPersistenceService; -import org.onap.cps.spi.CpsModulePersistenceService; -import org.onap.cps.spi.entities.DataspaceEntity; -import org.onap.cps.spi.entities.SchemaSetEntity; -import org.onap.cps.spi.entities.YangResourceEntity; -import org.onap.cps.spi.exceptions.DataspaceNotFoundException; -import org.onap.cps.spi.exceptions.SchemaSetAlreadyDefinedException; -import org.onap.cps.spi.exceptions.SchemaSetInUseException; -import org.onap.cps.spi.exceptions.SchemaSetNotFoundException; -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.SchemaSetRepository; -import org.onap.cps.spi.repository.YangResourceRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.jdbc.Sql; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest -public class CpsModulePersistenceServiceTest { - - private static final String CLEAR_DATA = "/data/clear-all.sql"; - private static final String SET_DATA = "/data/schemaset.sql"; - - private static final String ANCHOR_NAME = "ANCHOR-001"; - private static final String DATASPACE_NAME = "DATASPACE-001"; - private static final String DATASPACE_NAME_INVALID = "DATASPACE-X"; - private static final String SCHEMA_SET_NAME = "SCHEMA-SET-001"; - private static final String SCHEMA_SET_NAME_NEW = "SCHEMA-SET-NEW"; - private static final String SCHEMA_SET_NAME_NO_ANCHORS = "SCHEMA-SET-100"; - private static final String SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA = "SCHEMA-SET-101"; - - private static final String EXISTING_RESOURCE_NAME = "module1@2020-02-02.yang"; - private static final String EXISTING_RESOURCE_CONTENT = "CONTENT-001"; - private static final String EXISTING_RESOURCE_CHECKSUM = "877e65a9f36d54e7702c3f073f6bc42b"; - private static final Long EXISTING_RESOURCE_ID = 3001L; - - private static final String NEW_RESOURCE_NAME = "new-module@2020-02-02.yang"; - private static final String NEW_RESOURCE_CONTENT = "CONTENT-NEW"; - private static final String NEW_RESOURCE_CHECKSUM = "c94d40a1350eb1c0b1c1949eac84fc59"; - private static final Long NEW_RESOURCE_ABSTRACT_ID = 0L; - - private static final Long SHARED_RESOURCE_ID1 = 3003L; - private static final Long SHARED_RESOURCE_ID2 = 3004L; - private static final Long ORPHAN_RESOURCE_ID = 3100L; - private static final Integer REMOVED_ANCHOR_ID1 = 6001; - private static final Integer REMOVED_ANCHOR_ID2 = 6002; - private static final Long REMOVED_FRAGMENT_ID = 7001L; - - @ClassRule - public static DatabaseTestContainer testContainer = DatabaseTestContainer.getInstance(); - - @Autowired - private CpsModulePersistenceService cpsModulePersistenceService; - - @Autowired - private CpsAdminPersistenceService cpsAdminPersistenceService; - - @Autowired - DataspaceRepository dataspaceRepository; - - @Autowired - private SchemaSetRepository schemaSetRepository; - - @Autowired - private YangResourceRepository yangResourceRepository; - - @Autowired - private AnchorRepository anchorRepository; - - @Autowired - private FragmentRepository fragmentRepository; - - @Test(expected = DataspaceNotFoundException.class) - @Sql(CLEAR_DATA) - public void testStoreSchemaSetToInvalidDataspace() { - cpsModulePersistenceService.storeSchemaSet(DATASPACE_NAME_INVALID, SCHEMA_SET_NAME_NEW, - toMap(NEW_RESOURCE_NAME, NEW_RESOURCE_CONTENT)); - } - - @Test(expected = SchemaSetAlreadyDefinedException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreDuplicateSchemaSet() { - cpsModulePersistenceService.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME, - toMap(NEW_RESOURCE_NAME, NEW_RESOURCE_CONTENT)); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreSchemaSetWithNewYangResource() { - final Map yangResourcesNameToContentMap = toMap(NEW_RESOURCE_NAME, NEW_RESOURCE_CONTENT); - cpsModulePersistenceService.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, - yangResourcesNameToContentMap); - assertSchemaSetPersisted(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, - NEW_RESOURCE_ABSTRACT_ID, NEW_RESOURCE_NAME, NEW_RESOURCE_CONTENT, NEW_RESOURCE_CHECKSUM); - assertEquals(yangResourcesNameToContentMap, - cpsModulePersistenceService.getYangSchemaResources(DATASPACE_NAME, SCHEMA_SET_NAME_NEW)); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testGetYangResourcesWithAnchorName() { - final Map yangResourcesNameToContentMap = - toMap(NEW_RESOURCE_NAME, NEW_RESOURCE_CONTENT); - cpsModulePersistenceService.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, - yangResourcesNameToContentMap); - - cpsAdminPersistenceService.createAnchor(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, ANCHOR_NAME); - assertEquals(yangResourcesNameToContentMap, - cpsModulePersistenceService.getYangSchemaSetResources(DATASPACE_NAME, ANCHOR_NAME)); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testStoreSchemaSetWithExistingYangResourceReuse() { - cpsModulePersistenceService.storeSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, - toMap(NEW_RESOURCE_NAME, EXISTING_RESOURCE_CONTENT)); - assertSchemaSetPersisted(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, - EXISTING_RESOURCE_ID, EXISTING_RESOURCE_NAME, EXISTING_RESOURCE_CONTENT, EXISTING_RESOURCE_CHECKSUM); - } - - private void assertSchemaSetPersisted(final String expectedDataspaceName, final String expectedSchemaSetName, - final Long expectedYangResourceId, final String expectedYangResourceName, - final String expectedYangResourceContent, - final String expectedYangResourceChecksum) { - - // assert the schema set is persisted - final SchemaSetEntity schemaSetEntity = getSchemaSetFromDatabase(expectedDataspaceName, expectedSchemaSetName); - assertEquals(expectedDataspaceName, schemaSetEntity.getDataspace().getName()); - assertEquals(expectedSchemaSetName, schemaSetEntity.getName()); - - // assert the attached yang resource is persisted - final Set yangResourceEntities = schemaSetEntity.getYangResources(); - assertNotNull(yangResourceEntities); - assertEquals(1, yangResourceEntities.size()); - - // assert the attached yang resource content - final YangResourceEntity yangResourceEntity = yangResourceEntities.iterator().next(); - assertNotNull(yangResourceEntity.getId()); - if (expectedYangResourceId != NEW_RESOURCE_ABSTRACT_ID) { - // existing resource with known id - assertEquals(expectedYangResourceId, yangResourceEntity.getId()); - } - assertEquals(expectedYangResourceName, yangResourceEntity.getName()); - assertEquals(expectedYangResourceContent, yangResourceEntity.getContent()); - assertEquals(expectedYangResourceChecksum, yangResourceEntity.getChecksum()); - } - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testStrictDeleteSchemaSetNoAnchors() { - cpsModulePersistenceService.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NO_ANCHORS, - CASCADE_DELETE_PROHIBITED); - - // validate schema set removed - final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(DATASPACE_NAME); - assertFalse(schemaSetRepository - .findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_NO_ANCHORS).isPresent()); - - // validate shared resource remain, but orphan one is removed - assertTrue(yangResourceRepository.findById(SHARED_RESOURCE_ID1).isPresent()); - assertFalse(yangResourceRepository.findById(ORPHAN_RESOURCE_ID).isPresent()); - } - - - @Test - @Sql({CLEAR_DATA, SET_DATA}) - public void testFullDeleteSchemaSetWithAnchorsAndData() { - cpsModulePersistenceService - .deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA, CASCADE_DELETE_ALLOWED); - - // validate schema set removed - final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(DATASPACE_NAME); - assertFalse(schemaSetRepository - .findByDataspaceAndName(dataspaceEntity, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA).isPresent()); - - // validate shared resources remain - assertTrue(yangResourceRepository.findById(SHARED_RESOURCE_ID1).isPresent()); - assertTrue(yangResourceRepository.findById(SHARED_RESOURCE_ID2).isPresent()); - - // validate associated anchors and data are removed - assertFalse(anchorRepository.findById(REMOVED_ANCHOR_ID1).isPresent()); - assertFalse(anchorRepository.findById(REMOVED_ANCHOR_ID2).isPresent()); - assertFalse(fragmentRepository.findById(REMOVED_FRAGMENT_ID).isPresent()); - } - - @Test(expected = DataspaceNotFoundException.class) - @Sql(CLEAR_DATA) - public void testDeleteSchemaSetWithinInvalidDataspace() { - cpsModulePersistenceService.deleteSchemaSet(DATASPACE_NAME_INVALID, SCHEMA_SET_NAME, CASCADE_DELETE_ALLOWED); - } - - @Test(expected = SchemaSetNotFoundException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testDeleteNonExistingSchemaSet() { - cpsModulePersistenceService.deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_NEW, CASCADE_DELETE_ALLOWED); - } - - @Test(expected = SchemaSetInUseException.class) - @Sql({CLEAR_DATA, SET_DATA}) - public void testStrictDeleteSchemaSetInUse() { - cpsModulePersistenceService - .deleteSchemaSet(DATASPACE_NAME, SCHEMA_SET_NAME_WITH_ANCHORS_AND_DATA, CASCADE_DELETE_PROHIBITED); - } - - private static Map toMap(final String key, final String value) { - return ImmutableMap.builder().put(key, value).build(); - } - - private SchemaSetEntity getSchemaSetFromDatabase(final String dataspaceName, final String schemaSetName) { - final DataspaceEntity dataspaceEntity = dataspaceRepository.findByName(dataspaceName).orElseThrow(); - return schemaSetRepository.findByDataspaceAndName(dataspaceEntity, schemaSetName).orElseThrow(); - } -} -- 2.16.6