diff options
author | ToineSiebelink <toine.siebelink@est.tech> | 2023-02-23 15:49:40 +0000 |
---|---|---|
committer | ToineSiebelink <toine.siebelink@est.tech> | 2023-02-27 16:11:01 +0000 |
commit | 048350463a68b774f42e80e94afe16a541711ae4 (patch) | |
tree | 56d9d921813419d39fdd5e9cb7ebe47109f046ca /integration-test/src/test | |
parent | 003de55a8e6c53643032731e68edc43c0698fd81 (diff) |
Expand CPS Service Integration Test (framework)
- Created package structure
- Created several test bases
- Created complete test set for Admin service
- Created first test for Data service
- Added human-readable toString() to FetchDescendantsOption for test reporting and debuging purposes
- Renamed fetch descendants (enum) direct children option for consistency with others options
- TODO: Add sample performance test (and base)
Issue-ID: CPS-475
Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Change-Id: I75317686161be41662b6bf81314a9cd425ddd6eb
Diffstat (limited to 'integration-test/src/test')
-rw-r--r-- | integration-test/src/test/groovy/org/onap/cps/integration/CpsPersistenceSpec.groovy | 62 | ||||
-rw-r--r-- | integration-test/src/test/groovy/org/onap/cps/integration/base/BookstoreSpecBase.groovy | 49 | ||||
-rw-r--r-- | integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/CpsIntegrationSpecBase.groovy) | 61 | ||||
-rw-r--r-- | integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy (renamed from integration-test/src/test/groovy/org/onap/cps/integration/TestConfig.groovy) | 2 | ||||
-rw-r--r-- | integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAdminServiceIntegrationSpec.groovy | 109 | ||||
-rw-r--r-- | integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy | 48 |
6 files changed, 229 insertions, 102 deletions
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 deleted file mode 100644 index 349f0854ef..0000000000 --- a/integration-test/src/test/groovy/org/onap/cps/integration/CpsPersistenceSpec.groovy +++ /dev/null @@ -1,62 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2023 Nordix Foundation - * Modifications Copyright (C) 2023 TechMahindra Ltd. - * ================================================================================ - * 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.getDataNodes(TEST_DATASPACE, TEST_ANCHOR, '/bookstore', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS).iterator().next().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.getDataNodes(TEST_DATASPACE, TEST_ANCHOR, '/bookstore', FetchDescendantsOption.OMIT_DESCENDANTS).iterator().next().leaves['bookstore-name'] == 'Easons' - } -} diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/BookstoreSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/BookstoreSpecBase.groovy new file mode 100644 index 0000000000..7eb47b35ae --- /dev/null +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/BookstoreSpecBase.groovy @@ -0,0 +1,49 @@ +/* + * ============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.base + +import java.time.OffsetDateTime + +class BookstoreSpecBase extends CpsIntegrationSpecBase { + + def static initialized = false + + def setup() { + if (!initialized) { + setupBookstoreInfraStructure() + addBookstoreData() + initialized = true + } + } + + def setupBookstoreInfraStructure() { + cpsAdminService.createDataspace(BOOKSTORE_DATASPACE) + def bookstoreYangModelAsString = readResourceFile('bookstore.yang') + cpsModuleService.createSchemaSet(BOOKSTORE_DATASPACE, BOOKSTORE_SCHEMA_SET, [bookstore : bookstoreYangModelAsString]) + cpsAdminService.createAnchor(BOOKSTORE_DATASPACE, BOOKSTORE_SCHEMA_SET, BOOKSTORE_ANCHOR) + } + + def addBookstoreData() { + def bookstoreJsonData = readResourceFile('BookstoreDataNodes.json') + cpsDataService.saveData(BOOKSTORE_DATASPACE, BOOKSTORE_ANCHOR, bookstoreJsonData, OffsetDateTime.now()) + } + +} diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy index 960483270b..567b33cb46 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/CpsIntegrationSpecBase.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy @@ -18,15 +18,15 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.integration +package org.onap.cps.integration.base 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.integration.DatabaseTestContainer +import org.onap.cps.spi.model.DataNode 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 @@ -38,8 +38,6 @@ import org.testcontainers.spock.Testcontainers import spock.lang.Shared import spock.lang.Specification -import java.time.OffsetDateTime - @SpringBootTest(classes = [TestConfig, CpsAdminServiceImpl, CpsValidatorImpl]) @Testcontainers @EnableAutoConfiguration @@ -63,50 +61,35 @@ class CpsIntegrationSpecBase extends Specification { @Lazy CpsModuleServiceImpl cpsModuleService - - def static TEST_DATASPACE = 'testDataspace' + def static GENERAL_TEST_DATASPACE = 'generalTestDataSpace' + def static BOOKSTORE_DATASPACE = 'bookstoreDataspace' def static BOOKSTORE_SCHEMA_SET = 'bookstoreSchemaSet' - def static TEST_ANCHOR = 'testAnchor' + def static BOOKSTORE_ANCHOR = 'bookstoreAnchor' - def createDataspaceSchemaSetAnchor(String dataspaceName, String schemaSetName, String schemaSetFileName, String anchorName) { - cpsAdminService.createDataspace(dataspaceName) - createSchemaSetAnchor(dataspaceName, schemaSetName, schemaSetFileName, anchorName) - } + def static initialized = false - 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 setup() { + if (!initialized) { + cpsAdminService.createDataspace(GENERAL_TEST_DATASPACE) + def bookstoreModelFileContent = readResourceFile('bookstore.yang') + cpsModuleService.createSchemaSet(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, [bookstore : bookstoreModelFileContent]) + initialized = true; + } } - 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 static countDataNodesInTree(DataNode dataNode) { + return 1 + countDataNodesInTree(dataNode.getChildDataNodes()) } - 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 countDataNodesInTree(Collection<DataNode> dataNodes) { + int nodeCount = 0 + for (DataNode parent : dataNodes) { + nodeCount += countDataNodesInTree(parent) } + return nodeCount } - def static readResourceFile(String filename) { + def static readResourceFile(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/TestConfig.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy index 0673f7eb43..18a2941615 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/TestConfig.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/TestConfig.groovy @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.cps.integration +package org.onap.cps.integration.base import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.notification.NotificationService diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAdminServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAdminServiceIntegrationSpec.groovy new file mode 100644 index 0000000000..d504a9e0dd --- /dev/null +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsAdminServiceIntegrationSpec.groovy @@ -0,0 +1,109 @@ +/* + * ============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.functional + +import org.onap.cps.integration.base.CpsIntegrationSpecBase +import org.onap.cps.spi.exceptions.AlreadyDefinedException +import org.onap.cps.spi.exceptions.AnchorNotFoundException +import org.onap.cps.spi.exceptions.DataspaceNotFoundException + +class CpsAdminServiceIntegrationSpec extends CpsIntegrationSpecBase { + + def objectUnderTest + + def setup() { objectUnderTest = cpsAdminService } + + def 'Dataspace CRUD operations.'() { + when: 'a dataspace is created' + objectUnderTest.createDataspace('newDataspace') + then: 'the dataspace can be read' + assert objectUnderTest.getDataspace('newDataspace').name == 'newDataspace' + and: 'it can be deleted' + objectUnderTest.deleteDataspace('newDataspace') + then: 'the dataspace no longer exists i.e. an exception is thrown if an attempt is made to retrieve it' + def thrown = null + try { + objectUnderTest.getDataspace('newDataspace') + } catch(Exception e) { + thrown = e + } + assert thrown instanceof DataspaceNotFoundException + } + + def 'Retrieve all dataspaces (depends on total test suite).'() { + given: 'two addtional dataspaces are created' + objectUnderTest.createDataspace('dataspace1') + objectUnderTest.createDataspace('dataspace2') + when: 'all datespaces are retreived' + def result = objectUnderTest.getAllDataspaces() + then: 'there are at least 3 dataspaces (2 new ones plus the general test dataspace)' + result.size() >= 3 + assert result.name.containsAll([GENERAL_TEST_DATASPACE, 'dataspace1', 'dataspace2']) + } + + def 'Duplicate dataspaces.'() { + when: 'attempting to create a dataspace with the same name as an existing one' + objectUnderTest.createDataspace(GENERAL_TEST_DATASPACE) + then: 'an exception is thrown indicating the dataspace already exists' + thrown(AlreadyDefinedException) + } + + def 'Anchor CRUD operations.'() { + when: 'a anchor is created' + objectUnderTest.createAnchor(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'newAnchor') + then: 'the anchor be read' + assert objectUnderTest.getAnchor(GENERAL_TEST_DATASPACE, 'newAnchor').name == 'newAnchor' + and: 'it can be deleted' + objectUnderTest.deleteAnchor(GENERAL_TEST_DATASPACE,'newAnchor') + then: 'the anchor no longer exists i.e. an exception is thrown if an attempt is made to retrieve it' + def thrown = null + try { + objectUnderTest.getAnchor(GENERAL_TEST_DATASPACE, 'newAnchor') + } catch(Exception e) { + thrown = e + } + assert thrown instanceof AnchorNotFoundException + } + + def 'Filtering multiple anchors.'() { + when: '2 anchors with bookstore schema set are created' + objectUnderTest.createAnchor(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'anchor1') + objectUnderTest.createAnchor(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET, 'anchor2') + and: '1 anchor with "other" schema set is created' + def bookstoreModelFileContent = readResourceFile('bookstore.yang') + cpsModuleService.createSchemaSet(GENERAL_TEST_DATASPACE, 'otherSchemaSet', [someFileName: bookstoreModelFileContent]) + objectUnderTest.createAnchor(GENERAL_TEST_DATASPACE, 'otherSchemaSet', 'anchor3') + then: 'there are 3 anchors in the general test database' + assert objectUnderTest.getAnchors(GENERAL_TEST_DATASPACE).size() == 3 + and: 'there are 2 anchors associated with bookstore schema set' + assert objectUnderTest.getAnchors(GENERAL_TEST_DATASPACE, BOOKSTORE_SCHEMA_SET).size() == 2 + and: 'there is 1 anchor associated with other schema set' + assert objectUnderTest.getAnchors(GENERAL_TEST_DATASPACE, 'otherSchemaSet').size() == 1 + } + + def 'Querying anchor(name)s (depends on previous test!).'() { + expect: 'there are now 3 anchors using the "stores" module (both schema sets use the same modules) ' + assert objectUnderTest.queryAnchorNames(GENERAL_TEST_DATASPACE, ['stores']).size() == 3 + and: 'there are no anchors using both "stores" and a "unused-model"' + assert objectUnderTest.queryAnchorNames(GENERAL_TEST_DATASPACE, ['stores', 'unused-model']).size() == 0 + } + +} diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy new file mode 100644 index 0000000000..5e839f27a8 --- /dev/null +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy @@ -0,0 +1,48 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation + * Modifications Copyright (C) 2023 TechMahindra Ltd. + * ================================================================================ + * 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.functional + +import org.onap.cps.integration.base.BookstoreSpecBase +import org.onap.cps.spi.FetchDescendantsOption + +class CpsDataServiceIntegrationSpec extends BookstoreSpecBase { + + def objectUnderTest + + def setup() { objectUnderTest = cpsDataService } + + def 'Read bookstore top-level container(s) using #fetchDescendantsOption.'() { + when: 'get data nodes for bookstore container' + def result = objectUnderTest.getDataNodes(BOOKSTORE_DATASPACE, BOOKSTORE_ANCHOR, '/bookstore', fetchDescendantsOption) + then: 'the tree consist ouf of #expectNumberOfDataNodes data nodes' + assert countDataNodesInTree(result) == expectNumberOfDataNodes + and: 'the top level data node has the expected attribute and value' + assert result.leaves['bookstore-name'] == ['Easons'] + where: 'the following option is used' + fetchDescendantsOption || expectNumberOfDataNodes + FetchDescendantsOption.OMIT_DESCENDANTS || 1 + FetchDescendantsOption.DIRECT_CHILDREN_ONLY || 4 + FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS || 8 + new FetchDescendantsOption(2) || 8 + } + +} |