diff options
author | 2022-08-02 12:26:46 +0000 | |
---|---|---|
committer | 2022-08-02 12:26:46 +0000 | |
commit | 7a75eea4e388a04d8b67610ef53ed16db75489e6 (patch) | |
tree | 75664b32b00cb5df106ec58a15e4c3e0f337b8a3 /cps-ncmp-service/src/test/groovy/org | |
parent | b3c2b74c5a90750978a051cc9c8a6933f77e7948 (diff) | |
parent | 82a550f6b080cb50912d93f7b13ba0fc97a95470 (diff) |
Merge "Query CmHandles using CPS path"
Diffstat (limited to 'cps-ncmp-service/src/test/groovy/org')
4 files changed, 266 insertions, 157 deletions
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy index 7cf572ddb..40ec12da8 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy @@ -20,8 +20,14 @@ package org.onap.cps.ncmp.api.impl +import org.onap.cps.cpspath.parser.PathParsingException import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.ncmp.api.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle +import org.onap.cps.spi.FetchDescendantsOption +import org.onap.cps.spi.exceptions.DataInUseException +import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.model.Anchor import org.onap.cps.spi.model.CmHandleQueryServiceParameters import org.onap.cps.spi.model.ConditionProperties @@ -32,87 +38,127 @@ import java.util.stream.Collectors class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification { + def cmHandleQueries = Mock(CmHandleQueries) def inventoryPersistence = Mock(InventoryPersistence) - NetworkCmProxyCmHandlerQueryService objectUnderTest = new NetworkCmProxyCmHandlerQueryServiceImpl(inventoryPersistence) + def static someCmHandleDataNode = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'some-cmhandle-id\']', leaves: ['id':'some-cmhandle-id']) + def dmiRegistry = new DataNode(xpath: '/dmi-registry', childDataNodes: createDataNodeList(['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'])) - def 'Retrieve cm handles with public properties when #scenario.'() { - given: 'a condition property' + def objectUnderTest = new NetworkCmProxyCmHandlerQueryServiceImpl(cmHandleQueries, inventoryPersistence) + + def 'Retrieve cm handles with cpsPath when combined with no Module Query.'() { + given: 'a cmHandleWithCpsPath condition property' def cmHandleQueryParameters = new CmHandleQueryServiceParameters() - def conditionProperties = new ConditionProperties() - conditionProperties.conditionName = 'hasAllProperties' - conditionProperties.conditionParameters = publicProperties + def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) - and: 'mock services' - mockResponses() - when: 'a query is execute (with and without Data)' + and: 'cmHandleQueries returns a non null query result' + cmHandleQueries.getCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])] + and: 'CmHandleQueries returns cmHandles with the relevant query result' + cmHandleQueries.combineCmHandleQueries(*_) >> ['PNFDemo1': new NcmpServiceCmHandle(cmHandleId: 'PNFDemo1'), 'PNFDemo3': new NcmpServiceCmHandle(cmHandleId: 'PNFDemo3')] + when: 'the query is executed for both cm handle ids and details' def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters) then: 'the correct expected cm handles ids are returned' - returnedCmHandlesJustIds == expectedCmHandleIds as Set - and: 'the correct cm handle data objects are returned' - returnedCmHandlesWithData.stream().map(dataNode -> dataNode.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set + returnedCmHandlesJustIds == ['PNFDemo1', 'PNFDemo3'] as Set + and: 'the correct ncmp service cm handles are returned' + returnedCmHandlesWithData.stream().map(CmHandle -> CmHandle.cmHandleId).collect(Collectors.toSet()) == ['PNFDemo1', 'PNFDemo3'] as Set + } + + def 'Retrieve cm handles with cpsPath where #scenario.'() { + given: 'a cmHandleWithCpsPath condition property' + def cmHandleQueryParameters = new CmHandleQueryServiceParameters() + def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) + cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) + and: 'cmHandleQueries throws a path parsing exception' + cmHandleQueries.getCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> { throw thrownException } + when: 'the query is executed for both cm handle ids and details' + objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) + objectUnderTest.queryCmHandles(cmHandleQueryParameters) + then: 'a data validation exception is thrown' + thrown(expectedException) where: 'the following data is used' - scenario | publicProperties || expectedCmHandleIds - 'single property matches' | [['Contact' : 'newemailforstore@bookstore.com']] || ['PNFDemo1', 'PNFDemo2', 'PNFDemo4'] - 'public property does not match' | [['wont_match' : 'wont_match']] || [] - '2 properties, only one match' | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': 'newemailforstore2@bookstore.com']] || ['PNFDemo4'] - '2 properties, no matches' | [['Contact' : 'newemailforstore@bookstore.com'], ['Contact2': '']] || [] + scenario | thrownException || expectedException + 'a PathParsingException is thrown' | new PathParsingException('some message', 'some details') || DataValidationException + 'any other Exception is thrown' | new DataInUseException('some message', 'some details') || DataInUseException } - def 'Retrieve cm handles with module names when #scenario.'() { - given: 'a condition property' + def 'Query cm handles with public properties when combined with empty modules query result.'() { + given: 'a public properties condition property' def cmHandleQueryParameters = new CmHandleQueryServiceParameters() - def conditionProperties = new ConditionProperties() - conditionProperties.conditionName = 'hasAllModules' - conditionProperties.conditionParameters = moduleNames + def conditionProperties = createConditionProperties('hasAllProperties', [['some-property-key': 'some-property-value']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) - and: 'mock services' - mockResponses() - when: 'the service is invoked' + and: 'CmHandleQueries returns cmHandles with the relevant query result' + cmHandleQueries.combineCmHandleQueries(*_) >> ['PNFDemo1': new NcmpServiceCmHandle(cmHandleId: 'PNFDemo1'), 'PNFDemo3': new NcmpServiceCmHandle(cmHandleId: 'PNFDemo3')] + when: 'the query is executed for both cm handle ids and details' def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters) - then: 'the correct expected cm handles are returned' + then: 'the correct expected cm handles ids are returned' + returnedCmHandlesJustIds == ['PNFDemo1', 'PNFDemo3'] as Set + and: 'the correct cm handle data objects are returned' + returnedCmHandlesWithData.stream().map(dataNode -> dataNode.cmHandleId).collect(Collectors.toSet()) == ['PNFDemo1', 'PNFDemo3'] as Set + } + + def 'Retrieve cm handles with module names when #scenario from query.'() { + given: 'a modules condition property' + def cmHandleQueryParameters = new CmHandleQueryServiceParameters() + def conditionProperties = createConditionProperties('hasAllModules', [['moduleName': 'some-module-name']]) + cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) + and: 'null is returned from the state and public property queries' + cmHandleQueries.combineCmHandleQueries(*_) >> null + and: '#scenario from the modules query' + inventoryPersistence.queryAnchors(*_) >> returnedAnchors + and: 'the same cmHandles are returned from the persistence service layer' + returnedAnchors.size() * inventoryPersistence.getDataNode(*_) >> returnedCmHandles + when: 'the query is executed for both cm handle ids and details' + def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) + def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters) + then: 'the correct expected cm handles ids are returned' returnedCmHandlesJustIds == expectedCmHandleIds as Set + and: 'the correct cm handle data objects are returned' returnedCmHandlesWithData.stream().map(dataNode -> dataNode.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set where: 'the following data is used' - scenario | moduleNames || expectedCmHandleIds - 'single matching module name' | [['moduleName' : 'MODULE-NAME-001']] || ['PNFDemo3', 'PNFDemo1', 'PNFDemo2'] - 'module name dont match' | [['moduleName' : 'MODULE-NAME-004']] || [] - '2 module names, only one match' | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-003']] || ['PNFDemo4'] - '2 module names, no matches' | [['moduleName' : 'MODULE-NAME-002'], ['moduleName': 'MODULE-NAME-004']] || [] + scenario | returnedAnchors | returnedCmHandles || expectedCmHandleIds + 'One anchor returned' | [new Anchor(name: 'some-cmhandle-id')] | someCmHandleDataNode || ['some-cmhandle-id'] + 'No anchors are returned' | [] | null || [] } def 'Retrieve cm handles with combined queries when #scenario.'() { - given: 'condition properties' + given: 'all condition properties used' def cmHandleQueryParameters = new CmHandleQueryServiceParameters() - def conditionProperties1 = new ConditionProperties() - conditionProperties1.conditionName = 'hasAllProperties' - conditionProperties1.conditionParameters = publicProperties - def conditionProperties2 = new ConditionProperties() - conditionProperties2.conditionName = 'hasAllModules' - conditionProperties2.conditionParameters = moduleNames - cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties1,conditionProperties2]) - and: 'mock services' - mockResponses() - when: 'the service is invoked' + def conditionPubProps = createConditionProperties('hasAllProperties', [['some-property-key': 'some-property-value']]) + def conditionModules = createConditionProperties('hasAllModules', [['moduleName': 'some-module-name']]) + def conditionState = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) + cmHandleQueryParameters.setCmHandleQueryParameters([conditionPubProps, conditionModules, conditionState]) + and: 'cmHandles are returned from the state and public property combined queries' + cmHandleQueries.combineCmHandleQueries(*_) >> combinedQueryMap + and: 'cmHandles are returned from the module names query' + inventoryPersistence.queryAnchors(['some-module-name']) >> anchorsForModuleQuery + and: 'cmHandleQueries returns a datanode result' + 2 * cmHandleQueries.getCmHandleDataNodesByCpsPath(*_) >> [someCmHandleDataNode] + when: 'the query is executed for both cm handle ids and details' def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters) - then: 'the correct expected cm handles are returned' + then: 'the correct expected cm handles ids are returned' returnedCmHandlesJustIds == expectedCmHandleIds as Set - returnedCmHandlesWithData.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set + and: 'the correct cm handle data objects are returned' + returnedCmHandlesWithData.stream().map(dataNode -> dataNode.cmHandleId).collect(Collectors.toSet()) == expectedCmHandleIds as Set where: 'the following data is used' - scenario | moduleNames | publicProperties || expectedCmHandleIds - 'particularly intersect' | [['moduleName' : 'MODULE-NAME-001']] | [['Contact' : 'newemailforstore@bookstore.com']] || ['PNFDemo1', 'PNFDemo2'] - 'empty intersect' | [['moduleName' : 'MODULE-NAME-004']] | [['Contact' : 'newemailforstore@bookstore.com']] || [] - 'total intersect' | [['moduleName' : 'MODULE-NAME-002']] | [['Contact2' : 'newemailforstore2@bookstore.com']] || ['PNFDemo4'] + scenario | combinedQueryMap | anchorsForModuleQuery || expectedCmHandleIds + 'combined and modules queries intersect' | ['PNFDemo1' : new NcmpServiceCmHandle(cmHandleId:'PNFDemo1')] | [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2')] || ['PNFDemo1'] + 'only module query results exist' | [:] | [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2')] || [] + 'only combined query results exist' | ['PNFDemo1' : new NcmpServiceCmHandle(cmHandleId:'PNFDemo1'), 'PNFDemo2' : new NcmpServiceCmHandle(cmHandleId:'PNFDemo2')] | [] || [] + 'neither queries return results' | [:] | [] || [] + 'none intersect' | ['PNFDemo1' : new NcmpServiceCmHandle(cmHandleId:'PNFDemo1')] | [new Anchor(name: 'PNFDemo2')] || [] } def 'Retrieve cm handles when the query is empty.'() { - given: 'mock services' - mockResponses() - when: 'the service is invoked' + given: 'We use an empty query' def cmHandleQueryParameters = new CmHandleQueryServiceParameters() + and: 'the inventory persistence returns the dmi registry datanode' + inventoryPersistence.getDataNode("/dmi-registry") >> dmiRegistry + and: 'the inventory persistence returns anchors for get anchors' + inventoryPersistence.getAnchors() >> [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3'), new Anchor(name: 'PNFDemo4')] + when: 'the query is executed for both cm handle ids and details' def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters) then: 'the correct expected cm handles are returned' @@ -120,43 +166,13 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification { returnedCmHandlesWithData.stream().map(d -> d.cmHandleId).collect(Collectors.toSet()) == ['PNFDemo1', 'PNFDemo2', 'PNFDemo3', 'PNFDemo4'] as Set } - void mockResponses() { - def pNFDemo1 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo1\']', leaves: ['id':'PNFDemo1']) - def pNFDemo2 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo2\']', leaves: ['id':'PNFDemo2']) - def pNFDemo3 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo3\']', leaves: ['id':'PNFDemo3']) - def pNFDemo4 = new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'PNFDemo4\']', leaves: ['id':'PNFDemo4']) - def dmiRegistry = new DataNode(xpath: '/dmi-registry', childDataNodes: [pNFDemo1, pNFDemo2, pNFDemo3, pNFDemo4]) - - inventoryPersistence.queryDataNodes('//public-properties[@name=\'Contact\' and @value=\'newemailforstore@bookstore.com\']/ancestor::cm-handles') - >> [pNFDemo1, pNFDemo2, pNFDemo4] - inventoryPersistence.queryDataNodes('//public-properties[@name=\'wont_match\' and @value=\'wont_match\']/ancestor::cm-handles') - >> [] - inventoryPersistence.queryDataNodes('//public-properties[@name=\'Contact2\' and @value=\'newemailforstore2@bookstore.com\']/ancestor::cm-handles') - >> [pNFDemo4] - inventoryPersistence.queryDataNodes('//public-properties[@name=\'Contact2\' and @value=\'\']/ancestor::cm-handles') - >> [] - inventoryPersistence.queryDataNodes('//public-properties/ancestor::cm-handles') - >> [pNFDemo1, pNFDemo2, pNFDemo3, pNFDemo4] - - inventoryPersistence.queryDataNodes('//cm-handles[@id=\'PNFDemo\']') >> [pNFDemo1] - inventoryPersistence.queryDataNodes('//cm-handles[@id=\'PNFDemo2\']') >> [pNFDemo2] - inventoryPersistence.queryDataNodes('//cm-handles[@id=\'PNFDemo3\']') >> [pNFDemo3] - inventoryPersistence.queryDataNodes('//cm-handles[@id=\'PNFDemo4\']') >> [pNFDemo4] - - inventoryPersistence.getDataNode('/dmi-registry') >> dmiRegistry - - inventoryPersistence.getDataNode('/dmi-registry/cm-handles[@id=\'PNFDemo1\']') >> pNFDemo1 - inventoryPersistence.getDataNode('/dmi-registry/cm-handles[@id=\'PNFDemo2\']') >> pNFDemo2 - inventoryPersistence.getDataNode('/dmi-registry/cm-handles[@id=\'PNFDemo3\']') >> pNFDemo3 - inventoryPersistence.getDataNode('/dmi-registry/cm-handles[@id=\'PNFDemo4\']') >> pNFDemo4 + def createConditionProperties(String conditionName, List<Map<String, String>> conditionParameters) { + return new ConditionProperties(conditionName : conditionName, conditionParameters : conditionParameters) + } - inventoryPersistence.queryAnchors(['MODULE-NAME-001']) >> [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3')] - inventoryPersistence.queryAnchors(['MODULE-NAME-004']) >> [] - inventoryPersistence.queryAnchors(['MODULE-NAME-003', 'MODULE-NAME-002']) >> [new Anchor(name: 'PNFDemo4')] - inventoryPersistence.queryAnchors(['MODULE-NAME-002', 'MODULE-NAME-003']) >> [new Anchor(name: 'PNFDemo4')] - inventoryPersistence.queryAnchors(['MODULE-NAME-004', 'MODULE-NAME-002']) >> [] - inventoryPersistence.queryAnchors(['MODULE-NAME-002', 'MODULE-NAME-004']) >> [] - inventoryPersistence.queryAnchors(['MODULE-NAME-002']) >> [new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo4')] - inventoryPersistence.getAnchors() >> [new Anchor(name: 'PNFDemo1'), new Anchor(name: 'PNFDemo2'), new Anchor(name: 'PNFDemo3'), new Anchor(name: 'PNFDemo4')] + def static createDataNodeList(dataNodeIds) { + def dataNodes =[] + dataNodeIds.forEach(id -> {dataNodes.add(new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'' + id + '\']', leaves: ['id':id]))}) + return dataNodes } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy new file mode 100644 index 000000000..10a5d6246 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy @@ -0,0 +1,150 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2022 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.ncmp.api.inventory + +import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle +import org.onap.cps.spi.CpsDataPersistenceService +import org.onap.cps.spi.model.DataNode +import spock.lang.Shared +import spock.lang.Specification + +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS + +class CmHandleQueriesSpec extends Specification { + def cpsDataPersistenceService = Mock(CpsDataPersistenceService) + + def objectUnderTest = new CmHandleQueries(cpsDataPersistenceService) + + @Shared + def static sampleDataNodes = [new DataNode()] + + def static pnfDemo = createDataNode('PNFDemo') + def static pnfDemo2 = createDataNode('PNFDemo2') + def static pnfDemo3 = createDataNode('PNFDemo3') + def static pnfDemo4 = createDataNode('PNFDemo4') + + def static pnfDemoCmHandle = new NcmpServiceCmHandle(cmHandleId: 'PNFDemo') + def static pnfDemo2CmHandle = new NcmpServiceCmHandle(cmHandleId: 'PNFDemo2') + def static pnfDemo3CmHandle = new NcmpServiceCmHandle(cmHandleId: 'PNFDemo3') + + def 'Query CmHandles with public properties query pair.'() { + given: 'the DataNodes queried for a given cpsPath are returned from the persistence service.' + mockResponses() + when: 'a query on cmhandle public properties is performed with a public property pair' + def returnedCmHandlesWithData = objectUnderTest.queryCmHandlePublicProperties(publicPropertyPairs) + then: 'the correct cm handle data objects are returned' + returnedCmHandlesWithData.keySet().containsAll(expectedCmHandleIds) + returnedCmHandlesWithData.keySet().size() == expectedCmHandleIds.size() + where: 'the following data is used' + scenario | publicPropertyPairs || expectedCmHandleIds + 'single property matches' | ['Contact' : 'newemailforstore@bookstore.com'] || ['PNFDemo', 'PNFDemo2', 'PNFDemo4'] + 'public property does not match' | ['wont_match' : 'wont_match'] || [] + '2 properties, only one match' | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': 'newemailforstore2@bookstore.com'] || ['PNFDemo4'] + '2 properties, no matches' | ['Contact' : 'newemailforstore@bookstore.com', 'Contact2': ''] || [] + } + + def 'Query CmHandles using empty public properties query pair.'() { + when: 'a query on CmHandle public properties is executed using an empty map' + def returnedCmHandlesWithData = objectUnderTest.queryCmHandlePublicProperties([:]) + then: 'no cm handles are returned' + returnedCmHandlesWithData.keySet().size() == 0 + } + + def 'Combine two query results where #scenario.'() { + when: 'two query results in the form of a map of NcmpServiceCmHandles are combined into a single query result' + def result = objectUnderTest.combineCmHandleQueries(firstQuery, secondQuery) + then: 'the returned result is the same as the expected result' + result == expectedResult + where: + scenario | firstQuery | secondQuery || expectedResult + 'two queries with unique and non unique entries exist' | ['PNFDemo': pnfDemoCmHandle, 'PNFDemo2': pnfDemo2CmHandle] | ['PNFDemo': pnfDemoCmHandle, 'PNFDemo3': pnfDemo3CmHandle] || ['PNFDemo': pnfDemoCmHandle] + 'the first query contains entries and second query is empty' | ['PNFDemo': pnfDemoCmHandle, 'PNFDemo2': pnfDemo2CmHandle] | [:] || [:] + 'the second query contains entries and first query is empty' | [:] | ['PNFDemo': pnfDemoCmHandle, 'PNFDemo3': pnfDemo3CmHandle] || [:] + 'the first query contains entries and second query is null' | ['PNFDemo': pnfDemoCmHandle, 'PNFDemo2': pnfDemo2CmHandle] | null || ['PNFDemo': pnfDemoCmHandle, 'PNFDemo2': pnfDemo2CmHandle] + 'the second query contains entries and first query is null' | null | ['PNFDemo': pnfDemoCmHandle, 'PNFDemo3': pnfDemo3CmHandle] || ['PNFDemo': pnfDemoCmHandle, 'PNFDemo3': pnfDemo3CmHandle] + 'both queries are empty' | [:] | [:] || [:] + 'both queries are null' | null | null || [:] + } + + def 'Get Cm Handles By State'() { + given: 'a cm handle state to query' + def cmHandleState = CmHandleState.ADVISED + and: 'the persistence service returns a list of data nodes' + cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + '//state[@cm-handle-state="ADVISED"]/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> sampleDataNodes + when: 'cm handles are fetched by state' + def result = objectUnderTest.getCmHandlesByState(cmHandleState) + then: 'the returned result matches the result from the persistence service' + assert result == sampleDataNodes + } + + def 'Get Cm Handles By State and Cm-Handle Id'() { + given: 'a cm handle state to query' + def cmHandleState = CmHandleState.READY + and: 'cps data service returns a list of data nodes' + cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + '//cm-handles[@id=\'some-cm-handle\']/state[@cm-handle-state="'+ 'READY'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes + when: 'cm handles are fetched by state and id' + def result = objectUnderTest.getCmHandlesByIdAndState('some-cm-handle', cmHandleState) + then: 'the returned result is a list of data nodes returned by cps data service' + assert result == sampleDataNodes + } + + def 'Get Cm Handles By Operational Sync State : UNSYNCHRONIZED'() { + given: 'a cm handle state to query' + def cmHandleState = CmHandleState.READY + and: 'cps data service returns a list of data nodes' + cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + '//state/datastores/operational[@sync-state="'+'UNSYNCHRONIZED'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes + when: 'cm handles are fetched by the UNSYNCHRONIZED operational sync state' + def result = objectUnderTest.getCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) + then: 'the returned result is a list of data nodes returned by cps data service' + assert result == sampleDataNodes + } + + def 'Retrieve cm handle by cps path '() { + given: 'a cm handle state to query based on the cps path' + def cmHandleDataNode = new DataNode(xpath: 'xpath', leaves: ['cm-handle-state': 'LOCKED']) + def cpsPath = '//cps-path' + and: 'cps data service returns a valid data node' + cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', + cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) + >> Arrays.asList(cmHandleDataNode) + when: 'get cm handles by cps path is invoked' + def result = objectUnderTest.getCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) + then: 'the returned result is a list of data nodes returned by cps data service' + assert result.contains(cmHandleDataNode) + } + + void mockResponses() { + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact\" and @value=\"newemailforstore@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo2, pnfDemo4] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"wont_match\" and @value=\"wont_match\"]/ancestor::cm-handles', _) >> [] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"newemailforstore2@bookstore.com\"]/ancestor::cm-handles', _) >> [pnfDemo4] + cpsDataPersistenceService.queryDataNodes(_, _, '//public-properties[@name=\"Contact2\" and @value=\"\"]/ancestor::cm-handles', _) >> [] + cpsDataPersistenceService.queryDataNodes(_, _, '//state[@cm-handle-state=\"READY\"]/ancestor::cm-handles', _) >> [pnfDemo, pnfDemo3] + cpsDataPersistenceService.queryDataNodes(_, _, '//state[@cm-handle-state=\"LOCKED\"]/ancestor::cm-handles', _) >> [pnfDemo2, pnfDemo4] + } + + def static createDataNode(dataNodeId) { + return new DataNode(xpath: '/dmi-registry/cm-handles[@id=\'' + dataNodeId + '\']', leaves: ['id':dataNodeId]) + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy index 7ac231c16..f9ca676f3 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy @@ -80,9 +80,6 @@ class InventoryPersistenceSpec extends Specification { @Shared def childDataNodesForCmHandleWithState = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/state", leaves: ['cm-handle-state': 'ADVISED'])] - @Shared - def static sampleDataNodes = [new DataNode()] - def "Retrieve CmHandle using datanode with #scenario."() { given: 'the cps data service returns a data node from the DMI registry' def dataNode = new DataNode(childDataNodes:childDataNodes, leaves: leaves) @@ -157,56 +154,6 @@ class InventoryPersistenceSpec extends Specification { 'DELETING' | CmHandleState.DELETING || '{"state":{"cm-handle-state":"DELETING","last-update-time":"2022-12-31T20:30:40.000+0000"}}' } - def 'Get Cm Handles By State'() { - given: 'a cm handle state to query' - def cmHandleState = CmHandleState.ADVISED - and: 'cps data service returns a list of data nodes' - mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - '//state[@cm-handle-state="ADVISED"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes - when: 'get cm handles by state is invoked' - def result = objectUnderTest.getCmHandlesByState(cmHandleState) - then: 'the returned result is a list of data nodes returned by cps data service' - assert result == sampleDataNodes - } - - def 'Get Cm Handles By State and Cm-Handle Id'() { - given: 'a cm handle state to query' - def cmHandleState = CmHandleState.READY - and: 'cps data service returns a list of data nodes' - mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - '//cm-handles[@id=\'some-cm-handle\']/state[@cm-handle-state="'+ 'READY'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes - when: 'get cm handles by state and id is invoked' - def result = objectUnderTest.getCmHandlesByIdAndState(cmHandleId, cmHandleState) - then: 'the returned result is a list of data nodes returned by cps data service' - assert result == sampleDataNodes - } - - def 'Get Cm Handles By Operational Sync State : UNSYNCHRONIZED'() { - given: 'a cm handle state to query' - def cmHandleState = CmHandleState.READY - and: 'cps data service returns a list of data nodes' - mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - '//state/datastores/operational[@sync-state="'+'UNSYNCHRONIZED'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes - when: 'get cm handles by operational sync state as UNSYNCHRONIZED is invoked' - def result = objectUnderTest.getCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) - then: 'the returned result is a list of data nodes returned by cps data service' - assert result == sampleDataNodes - } - - def 'Retrieve cm handle by cps path '() { - given: 'a cm handle state to query based on the cps path' - def cmHandleDataNode = new DataNode(xpath: 'xpath', leaves: ['cm-handle-state': 'LOCKED']) - def cpsPath = '//cps-path' - and: 'cps data service returns a valid data node' - mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - cpsPath, INCLUDE_ALL_DESCENDANTS) - >> Arrays.asList(cmHandleDataNode) - when: 'get cm handles by cps path is invoked' - def result = objectUnderTest.getCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) - then: 'the returned result is a list of data nodes returned by cps data service' - assert result.contains(cmHandleDataNode) - } - def 'Get module definitions'() { given: 'cps module service returns a collection of module definitions' def moduleDefinitions = [new ModuleDefinition('moduleName','revision','content')] @@ -263,13 +210,6 @@ class InventoryPersistenceSpec extends Specification { 0 * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'sampleSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) } - def 'Query data nodes via cpsPath'() { - when: 'the method to query data nodes is called' - objectUnderTest.queryDataNodes('sample cpsPath') - then: 'the data persistence service method to query data nodes is invoked once' - 1 * mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin','ncmp-dmi-registry','sample cpsPath', INCLUDE_ALL_DESCENDANTS) - } - def 'Get data node via xPath'() { when: 'the method to get data nodes is called' objectUnderTest.getDataNode('sample xPath') diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy index 6c2d8f15b..82e9d33ae 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy @@ -25,6 +25,7 @@ import com.fasterxml.jackson.databind.JsonNode import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations import org.onap.cps.ncmp.api.impl.operations.DmiOperations +import org.onap.cps.ncmp.api.inventory.CmHandleQueries import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder @@ -47,11 +48,13 @@ class SyncUtilsSpec extends Specification{ def mockInventoryPersistence = Mock(InventoryPersistence) + def mockCmHandleQueries = Mock(CmHandleQueries) + def mockDmiDataOperations = Mock(DmiDataOperations) def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) - def objectUnderTest = new SyncUtils(mockInventoryPersistence, mockDmiDataOperations, jsonObjectMapper) + def objectUnderTest = new SyncUtils(mockInventoryPersistence, mockCmHandleQueries, mockDmiDataOperations, jsonObjectMapper) @Shared def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(OffsetDateTime.now()) @@ -61,14 +64,14 @@ class SyncUtilsSpec extends Specification{ def 'Get an advised Cm-Handle where ADVISED cm handle #scenario'() { given: 'the inventory persistence service returns a collection of data nodes' - mockInventoryPersistence.getCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection + mockCmHandleQueries.getCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection when: 'get advised cm handles are fetched' def yangModelCmHandles = objectUnderTest.getAdvisedCmHandles() then: 'the returned data node collection is the correct size' yangModelCmHandles.size() == expectedDataNodeSize and: 'yang model collection contains the correct data' yangModelCmHandles.stream().map(yangModel -> yangModel.id).collect(Collectors.toSet()) == - dataNodeCollection.stream().map(dataNode -> dataNode.leaves.get("id")).collect(Collectors.toSet()) + dataNodeCollection.stream().map(dataNode -> dataNode.leaves.get("id")).collect(Collectors.toSet()) where: 'the following scenarios are used' scenario | dataNodeCollection || expectedCallsToGetYangModelCmHandle | expectedDataNodeSize 'exists' | [dataNode] || 1 | 1 @@ -77,7 +80,7 @@ class SyncUtilsSpec extends Specification{ def 'Update Lock Reason, Details and Attempts where lock reason #scenario'() { given: 'A locked state' - def compositeState = new CompositeState(lockReason: lockReason) + def compositeState = new CompositeState(lockReason: lockReason) when: 'update cm handle details and attempts is called' objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, 'new error message') then: 'the composite state lock reason and details are updated' @@ -91,9 +94,9 @@ class SyncUtilsSpec extends Specification{ def 'Get all locked Cm-Handle where Lock Reason is LOCKED_MODULE_SYNC_FAILED cm handle #scenario'() { given: 'the cps (persistence service) returns a collection of data nodes' - mockInventoryPersistence.getCmHandleDataNodesByCpsPath( - '//lock-reason[@reason="LOCKED_MODULE_SYNC_FAILED"]/ancestor::cm-handles', - FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode ] + mockCmHandleQueries.getCmHandleDataNodesByCpsPath( + '//lock-reason[@reason="LOCKED_MODULE_SYNC_FAILED"]', + FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode] when: 'get locked Misbehaving cm handle is called' def result = objectUnderTest.getModuleSyncFailedCmHandles() then: 'the returned cm handle collection is the correct size' @@ -119,8 +122,8 @@ class SyncUtilsSpec extends Specification{ def 'Get a Cm-Handle where Operational Sync state is UnSynchronized and Cm-handle state is READY and #scenario'() { given: 'the inventory persistence service returns a collection of data nodes' - mockInventoryPersistence.getCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) >> unSynchronizedDataNodes - mockInventoryPersistence.getCmHandlesByIdAndState("cm-handle-123", CmHandleState.READY) >> readyDataNodes + mockCmHandleQueries.getCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) >> unSynchronizedDataNodes + mockCmHandleQueries.getCmHandlesByIdAndState("cm-handle-123", CmHandleState.READY) >> readyDataNodes when: 'get advised cm handles are fetched' objectUnderTest.getAnUnSynchronizedReadyCmHandle() then: 'the returned data node collection is the correct size' |