summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src/test/groovy
diff options
context:
space:
mode:
Diffstat (limited to 'cps-ncmp-service/src/test/groovy')
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy201
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy126
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapperSpec.groovy67
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy34
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy12
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy5
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy66
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy11
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy)88
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/CmHandleStateSpec.groovy46
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy58
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy45
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy6
15 files changed, 486 insertions, 295 deletions
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
index 5683d57e54..f56aea7f33 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
@@ -28,8 +28,7 @@ import org.onap.cps.api.CpsDataService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.ncmp.api.impl.exception.DmiRequestException
import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations
-import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
-import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse
import org.onap.cps.ncmp.api.models.DmiPluginRegistration
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
@@ -61,10 +60,9 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def mockCpsModuleService = Mock(CpsModuleService)
def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
def mockCpsAdminService = Mock(CpsAdminService)
- def mockDmiModelOperations = Mock(DmiModelOperations)
def mockDmiDataOperations = Mock(DmiDataOperations)
def mockNetworkCmProxyDataServicePropertyHandler = Mock(NetworkCmProxyDataServicePropertyHandler)
- def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever)
+ def mockInventoryPersistence = Mock(InventoryPersistence)
def mockModuleSyncService = Mock(ModuleSyncService)
def noTimestamp = null
@@ -389,6 +387,6 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def getObjectUnderTest() {
return Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations,
- mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler, mockYangModelCmHandleRetriever, mockModuleSyncService))
+ mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockModuleSyncService))
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
index 01f3bfed7b..55a1a8d1fa 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy
@@ -23,8 +23,10 @@
package org.onap.cps.ncmp.api.impl
import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
-import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.ncmp.api.inventory.CmHandleState
+import org.onap.cps.ncmp.api.inventory.CompositeState
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
import org.onap.cps.ncmp.api.models.DmiPluginRegistration
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.spi.exceptions.DataValidationException
@@ -34,11 +36,9 @@ import spock.lang.Shared
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
-import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
import org.onap.cps.utils.JsonObjectMapper
-import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.api.CpsAdminService
import org.onap.cps.api.CpsDataService
@@ -58,7 +58,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
def mockDmiDataOperations = Mock(DmiDataOperations)
def nullNetworkCmProxyDataServicePropertyHandler = null
- def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever)
+ def mockInventoryPersistence = Mock(InventoryPersistence)
def mockModuleSyncService = Mock(ModuleSyncService)
def mockDmiPluginRegistration = Mock(DmiPluginRegistration)
@@ -70,17 +70,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id')
def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations,
- mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockYangModelCmHandleRetriever, mockModuleSyncService)
+ mockCpsModuleService, mockCpsAdminService, nullNetworkCmProxyDataServicePropertyHandler, mockInventoryPersistence, mockModuleSyncService)
def cmHandleXPath = "/dmi-registry/cm-handles[@id='testCmHandle']"
def dataNode = new DataNode(leaves: ['id': 'some-cm-handle', 'dmi-service-name': 'testDmiService'])
- def 'Write resource data for pass-through running from DMI using POST #scenario cm handle properties.'() {
+ def 'Write resource data for pass-through running from DMI using POST.'() {
given: 'cpsDataService returns valid datanode'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- when: 'get resource data is called'
+ when: 'write resource data is called'
objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
'testResourceId', CREATE,
'{some-json}', 'application/json')
@@ -101,102 +101,26 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
0 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi(_, _, _, _, _)
}
- def 'Write resource data for pass-through running from DMI using POST "not found" response (from DMI).'() {
- given: 'cpsDataService returns valid dataNode'
- mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
- cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- and: 'DMI returns a response with 404 status code'
- mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi('testCmHandle',
- 'testResourceId', CREATE,
- '{some-json}', 'application/json')
- >> { new ResponseEntity<>(HttpStatus.NOT_FOUND) }
- when: 'write resource data is called'
- objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId', CREATE,
- '{some-json}', 'application/json')
- then: 'exception is thrown'
- def exceptionThrown = thrown(HttpClientRequestException.class)
- and: 'http status (not found) error code: 404'
- exceptionThrown.httpStatus == HttpStatus.NOT_FOUND.value()
- }
-
def 'Get resource data for pass-through operational from DMI.'() {
given: 'get data node is called'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
and: 'get resource data from DMI is called'
mockDmiDataOperations.getResourceDataFromDmi(
- 'testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- PASSTHROUGH_OPERATIONAL,
- NO_REQUEST_ID,
- NO_TOPIC) >> new ResponseEntity<>('dmi-response', HttpStatus.OK)
+ 'testCmHandle',
+ 'testResourceId',
+ OPTIONS_PARAM,
+ PASSTHROUGH_OPERATIONAL,
+ NO_REQUEST_ID,
+ NO_TOPIC) >> new ResponseEntity<>('dmi-response', HttpStatus.OK)
when: 'get resource data operational for cm-handle is called'
def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- NO_TOPIC,
- NO_REQUEST_ID)
- then: 'DMI returns a json response'
- response == 'dmi-response'
- }
-
- def 'Get resource data for pass-through operational from DMI with invalid name.'() {\
- when: 'get resource data operational for cm-handle is called'
- objectUnderTest.getResourceDataOperationalForCmHandle('invalid test cm handle',
'testResourceId',
OPTIONS_PARAM,
NO_TOPIC,
NO_REQUEST_ID)
- then: 'A data validation Exception is thrown'
- thrown(DataValidationException)
- }
-
- def 'Get resource data for pass-through operational from DMI with Json Processing Exception.'() {
- given: 'cps data service returns valid data node'
- mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
- cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- and: 'objectMapper not able to parse object'
- spiedJsonObjectMapper.asJsonString(_) >> { throw new JsonProcessingException('testException') }
- and: 'DMI returns NOK response'
- mockDmiDataOperations.getResourceDataFromDmi(*_)
- >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
- when: 'get resource data is called'
- objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- NO_TOPIC,
- NO_REQUEST_ID)
- then: 'exception is thrown with the expected response code and details'
- def exceptionThrown = thrown(HttpClientRequestException.class)
- exceptionThrown.details.contains('NOK-json')
- exceptionThrown.httpStatus == HttpStatus.NOT_FOUND.value()
- }
-
- def 'Get resource data for pass-through operational from DMI return NOK response.'() {
- given: 'cps data service returns valid data node'
- mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
- cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- and: 'DMI returns NOK response'
- mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- PASSTHROUGH_OPERATIONAL,
- NO_REQUEST_ID,
- NO_TOPIC)
- >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
- when: 'get resource data is called'
- objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- NO_TOPIC,
- NO_REQUEST_ID)
- then: 'exception is thrown'
- def exceptionThrown = thrown(HttpClientRequestException.class)
- and: 'details contain the original response'
- exceptionThrown.httpStatus == HttpStatus.NOT_FOUND.value()
- exceptionThrown.details.contains('NOK-json')
+ then: 'DMI returns a json response'
+ response == 'dmi-response'
}
def 'Get resource data for pass-through running from DMI.'() {
@@ -205,55 +129,19 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
and: 'DMI returns valid response and data'
mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- PASSTHROUGH_RUNNING,
- NO_REQUEST_ID,
- NO_TOPIC) >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
+ 'testResourceId',
+ OPTIONS_PARAM,
+ PASSTHROUGH_RUNNING,
+ NO_REQUEST_ID,
+ NO_TOPIC) >> new ResponseEntity<>('{dmi-response}', HttpStatus.OK)
when: 'get resource data is called'
def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- NO_TOPIC,
- NO_REQUEST_ID)
- then: 'get resource data returns expected response'
- response == '{dmi-response}'
- }
-
- def 'Get resource data for pass-through running from DMI with invalid name.'() {
- when: 'get resource data operational for cm-handle is called'
- objectUnderTest.getResourceDataPassThroughRunningForCmHandle('invalid test cm handle',
'testResourceId',
OPTIONS_PARAM,
NO_TOPIC,
NO_REQUEST_ID)
- then: 'A data validation Exception is thrown'
- thrown(DataValidationException)
- }
-
- def 'Get resource data for pass-through running from DMI return NOK response.'() {
- given: 'cpsDataService returns valid dataNode'
- mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
- cmHandleXPath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
- and: 'DMI returns NOK response'
- mockDmiDataOperations.getResourceDataFromDmi('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- PASSTHROUGH_RUNNING,
- NO_REQUEST_ID,
- NO_TOPIC)
- >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
- when: 'get resource data is called'
- objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
- 'testResourceId',
- OPTIONS_PARAM,
- NO_TOPIC,
- NO_REQUEST_ID)
- then: 'exception is thrown'
- def exceptionThrown = thrown(HttpClientRequestException.class)
- and: 'details contain the original response'
- exceptionThrown.details.contains('NOK-json')
- exceptionThrown.httpStatus == HttpStatus.NOT_FOUND.value()
+ then: 'get resource data returns expected response'
+ response == '{dmi-response}'
}
def 'Getting Yang Resources.'() {
@@ -269,7 +157,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
then: 'a data validation exception is thrown'
thrown(DataValidationException)
and: 'CPS module services is not invoked'
- 0 * mockCpsModuleService.getYangResourcesModuleReferences(_, _)
+ 0 * mockCpsModuleService.getYangResourcesModuleReferences(*_)
}
def 'Get cm handle identifiers for the given module names.'() {
@@ -284,15 +172,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def dmiServiceName = 'some service name'
def dmiProperties = [new YangModelCmHandle.Property('Book', 'Romance Novel')]
def publicProperties = [new YangModelCmHandle.Property('Public Book', 'Public Romance Novel')]
- def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: dmiServiceName, dmiProperties: dmiProperties, publicProperties: publicProperties)
- 1 * mockYangModelCmHandleRetriever.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
+ def compositeState = new CompositeState(cmHandleState: 'ADVISED')
+ def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', dmiServiceName: dmiServiceName,
+ dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
+ 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
when: 'getting cm handle details for a given cm handle id from ncmp service'
def result = objectUnderTest.getNcmpServiceCmHandle('some-cm-handle')
then: 'the result returns the correct data'
result.cmHandleId == 'some-cm-handle'
result.dmiProperties ==[ Book:'Romance Novel' ]
result.publicProperties == [ "Public Book":'Public Romance Novel' ]
-
+ result.compositeState.cmHandleState == CmHandleState.ADVISED
}
def 'Get a cm handle with an invalid id.'() {
@@ -301,7 +191,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
then: 'an exception is thrown'
thrown(DataValidationException)
and: 'the yang model cm handle retriever is not invoked'
- 0 * mockYangModelCmHandleRetriever.getYangModelCmHandle(_)
+ 0 * mockInventoryPersistence.getYangModelCmHandle(*_)
}
def 'Get cm handle public properties'() {
@@ -310,7 +200,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
def publicProperties = [new YangModelCmHandle.Property('public prop', 'some public prop')]
def yangModelCmHandle = new YangModelCmHandle(id:'some-cm-handle', dmiServiceName: 'some service name', dmiProperties: dmiProperties, publicProperties: publicProperties)
and: 'the system returns this yang modelled cm handle'
- 1 * mockYangModelCmHandleRetriever.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
+ 1 * mockInventoryPersistence.getYangModelCmHandle('some-cm-handle') >> yangModelCmHandle
when: 'getting cm handle public properties for a given cm handle id from ncmp service'
def result = objectUnderTest.getCmHandlePublicProperties('some-cm-handle')
then: 'the result returns the correct data'
@@ -323,7 +213,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
then: 'an exception is thrown'
thrown(DataValidationException)
and: 'the yang model cm handle retriever is not invoked'
- 0 * mockYangModelCmHandleRetriever.getYangModelCmHandle(_)
+ 0 * mockInventoryPersistence.getYangModelCmHandle(*_)
}
def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() {
@@ -340,40 +230,19 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
>> { new ResponseEntity<>(HttpStatus.OK) }
}
- def 'Verify error message from handleResponse is correct for #scenario operation.'() {
- given: 'writeResourceDataPassThroughRunningFromDmi fails to return OK HttpStatus'
- mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi(*_)
- >> new ResponseEntity<>(HttpStatus.NOT_FOUND)
- when: 'get resource data is called'
- objectUnderTest.writeResourceDataPassThroughRunningForCmHandle(
- 'testCmHandle',
- 'testResourceId',
- givenOperation,
- '{some-json}',
- 'application/json')
- then: 'an exception is thrown with the expected error message details with correct operation'
- def exceptionThrown = thrown(HttpClientRequestException.class)
- exceptionThrown.getMessage().contains(expectedResponseMessage)
- where:
- scenario | givenOperation || expectedResponseMessage
- 'CREATE' | CREATE || 'Unable to create resource data.'
- 'READ' | READ || 'Unable to read resource data.'
- 'UPDATE' | UPDATE || 'Unable to update resource data.'
- }
-
def 'Verify modules and create anchor params'() {
given: 'dmi plugin registration return created cm handles'
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'service1', dmiModelPlugin: 'service1',
- dmiDataPlugin: 'service2')
+ dmiDataPlugin: 'service2')
dmiPluginRegistration.createdCmHandles = [ncmpServiceCmHandle]
mockDmiPluginRegistration.getCreatedCmHandles() >> [ncmpServiceCmHandle]
when: 'parse and create cm handle in dmi registration then sync module'
objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(mockDmiPluginRegistration)
then: 'validate params for creating anchor and list elements'
1 * mockCpsDataService.saveListElements('NCMP-Admin', 'ncmp-dmi-registry',
- '/dmi-registry', '{"cm-handles":[{"id":"some-cm-handle-id",' +
- '"additional-properties":[],"public-properties":[]}]}', null)
+ '/dmi-registry', '{"cm-handles":[{"id":"some-cm-handle-id",' +
+ '"additional-properties":[],"public-properties":[]}]}', null)
1 * mockCpsAdminService.createAnchor('NFP-Operational', null,
- 'some-cm-handle-id')
+ 'some-cm-handle-id')
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy
new file mode 100644
index 0000000000..aa6bf1a783
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/CpsAsyncRequestResponseEventIntegrationSpec.groovy
@@ -0,0 +1,126 @@
+/*
+ * ============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.impl.async
+
+import org.apache.kafka.clients.consumer.ConsumerConfig
+import org.apache.kafka.clients.producer.ProducerConfig
+import org.apache.kafka.common.serialization.StringSerializer
+import org.mapstruct.factory.Mappers
+import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent
+import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent
+import org.springframework.kafka.core.DefaultKafkaProducerFactory
+import org.springframework.kafka.core.KafkaTemplate
+import org.springframework.kafka.support.serializer.JsonSerializer
+import org.testcontainers.containers.KafkaContainer
+import org.testcontainers.spock.Testcontainers
+import org.testcontainers.utility.DockerImageName
+
+import java.time.Duration
+import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.utils.JsonObjectMapper
+import org.apache.kafka.clients.consumer.KafkaConsumer
+import org.apache.kafka.common.serialization.StringDeserializer
+import org.onap.cps.ncmp.utils.TestUtils;
+import org.springframework.boot.test.context.SpringBootTest
+import org.spockframework.spring.SpringBean
+import org.springframework.test.annotation.DirtiesContext
+import org.springframework.test.context.DynamicPropertyRegistry
+import org.springframework.test.context.DynamicPropertySource
+import spock.lang.Specification
+
+@SpringBootTest(classes = [NcmpAsyncRequestResponseEventProducer, NcmpAsyncRequestResponseEventConsumer])
+@Testcontainers
+@DirtiesContext
+class NcmpAsyncRequestResponseEventProducerIntegrationSpec extends Specification {
+
+ static kafkaTestContainer = new KafkaContainer(
+ DockerImageName.parse('confluentinc/cp-kafka:6.2.1')
+ )
+
+ static {
+ Runtime.getRuntime().addShutdownHook(new Thread(kafkaTestContainer::stop))
+ }
+
+ def setupSpec() {
+ kafkaTestContainer.start()
+ }
+
+ def producerConfigProperties = [
+ (ProducerConfig.BOOTSTRAP_SERVERS_CONFIG) : kafkaTestContainer.getBootstrapServers().split(',')[0],
+ (ProducerConfig.RETRIES_CONFIG) : 0,
+ (ProducerConfig.BATCH_SIZE_CONFIG) : 16384,
+ (ProducerConfig.LINGER_MS_CONFIG) : 1,
+ (ProducerConfig.BUFFER_MEMORY_CONFIG) : 33554432,
+ (ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG) : StringSerializer,
+ (ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG) : JsonSerializer
+ ]
+
+ def consumerConfigProperties = [
+ (ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG) : kafkaTestContainer.getBootstrapServers().split(',')[0],
+ (ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG) : StringDeserializer,
+ (ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG): StringDeserializer,
+ (ConsumerConfig.AUTO_OFFSET_RESET_CONFIG) : 'earliest',
+ (ConsumerConfig.GROUP_ID_CONFIG) : 'test'
+ ]
+
+ def kafkaTemplate = new KafkaTemplate<>(new DefaultKafkaProducerFactory<Integer, String>(producerConfigProperties))
+
+ @SpringBean
+ NcmpAsyncRequestResponseEventProducer cpsAsyncRequestResponseEventProducerService =
+ new NcmpAsyncRequestResponseEventProducer(kafkaTemplate);
+
+ @SpringBean
+ NcmpAsyncRequestResponseEventMapper ncmpAsyncRequestResponseEventMapper =
+ Mappers.getMapper(NcmpAsyncRequestResponseEventMapper.class)
+
+ @SpringBean
+ NcmpAsyncRequestResponseEventConsumer ncmpAsyncRequestResponseEventConsumer =
+ new NcmpAsyncRequestResponseEventConsumer(cpsAsyncRequestResponseEventProducerService,
+ ncmpAsyncRequestResponseEventMapper)
+
+ def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+
+ def kafkaConsumer = new KafkaConsumer<>(getConsumerConfigProperties())
+
+ def 'Consume and forward valid message'() {
+ given: 'consumer has a subscription'
+ kafkaConsumer.subscribe(['test-topic'] as List<String>)
+ and: 'an event is sent'
+ def jsonData = TestUtils.getResourceFileContent('dmiAsyncRequestResponseEvent.json')
+ def testEventSent = jsonObjectMapper.convertJsonString(jsonData, DmiAsyncRequestResponseEvent.class)
+ when: 'the event is consumed'
+ ncmpAsyncRequestResponseEventConsumer.consumeAndForward(testEventSent)
+ and: 'the topic is polled'
+ def records = kafkaConsumer.poll(Duration.ofMillis(1500))
+ then: 'poll returns one record'
+ assert records.size() == 1
+ and: 'consumed forwarded event id is the same as sent event id'
+ def record = records.iterator().next()
+ assert testEventSent.eventId.equalsIgnoreCase(jsonObjectMapper.convertJsonString(record.value(),
+ NcmpAsyncRequestResponseEvent).getForwardedEvent().getEventId())
+ }
+
+ @DynamicPropertySource
+ static void registerKafkaProperties(DynamicPropertyRegistry dynamicPropertyRegistry) {
+ dynamicPropertyRegistry.add('spring.kafka.bootstrap-servers', kafkaTestContainer::getBootstrapServers)
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapperSpec.groovy
new file mode 100644
index 0000000000..07e9b49ff6
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/async/NcmpAsyncRequestResponseEventMapperSpec.groovy
@@ -0,0 +1,67 @@
+/*
+ * ============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.impl.async
+
+import org.mapstruct.factory.Mappers
+import org.onap.cps.ncmp.event.model.DmiAsyncRequestResponseEvent
+import org.onap.cps.ncmp.event.model.EventContent
+import org.onap.cps.ncmp.event.model.NcmpAsyncRequestResponseEvent
+import org.onap.cps.ncmp.event.model.ResponseData
+import spock.lang.Specification
+
+class NcmpAsyncRequestResponseEventMapperSpec extends Specification {
+
+ def objectUnderTest = Mappers.getMapper(NcmpAsyncRequestResponseEventMapper.class)
+
+ def 'Convert dmi async request response event to ncmp async request response event'() {
+ given: 'a dmi async request response event'
+ def dmiAsyncRequestResponseEvent = new DmiAsyncRequestResponseEvent()
+ .withEventCorrelationId("correlation-id-123").withEventContent(new EventContent()
+ .withResponseData(new ResponseData()))
+ and: 'the event Id and time are empty'
+ dmiAsyncRequestResponseEvent.withEventId('').withEventTime('')
+ when: 'mapper is called'
+ def result = objectUnderTest.toNcmpAsyncEvent(dmiAsyncRequestResponseEvent)
+ then: 'result is of the correct type'
+ assert result.class == NcmpAsyncRequestResponseEvent.class
+ and: 'eventId and eventTime should be overridden by custom method with non-empty values'
+ assert result.eventId != ''
+ assert result.eventTime != ''
+ and: 'target eventCorrelationId of mapped object should be same as source eventCorrelationId'
+ assert result.eventCorrelationId == "correlation-id-123"
+ }
+
+ def 'Dmi async request response event is mapped correctly to forwarded event'() {
+ given: 'a dmi async request response event'
+ def dmiAsyncRequestResponseEvent = new DmiAsyncRequestResponseEvent()
+ .withEventContent(new EventContent().withResponseCode('200')
+ .withResponseData(new ResponseData().withAdditionalProperty('property1', 'value1')
+ .withAdditionalProperty('property2', 'value2')))
+ when: 'mapper is called'
+ def result = objectUnderTest.toNcmpAsyncEvent(dmiAsyncRequestResponseEvent)
+ then: 'result is of the correct type'
+ assert result.class == NcmpAsyncRequestResponseEvent.class
+ and: 'forwarded event content response code is mapped correctly'
+ assert result.forwardedEvent.responseCode == '200'
+ and: 'after mapping additional properties should be stored'
+ result.forwardedEvent.additionalProperties.'response-data' == ['property2': 'value2', 'property1': 'value1']
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
index 394df1d076..90839f8ac0 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation
+ * Copyright (C) 2021-2022 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,17 +22,23 @@
package org.onap.cps.ncmp.api.impl.client
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
+import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpEntity
-import org.springframework.http.HttpHeaders
-import org.springframework.http.HttpMethod
+import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
+import org.springframework.web.client.HttpServerErrorException
import org.springframework.web.client.RestTemplate
import spock.lang.Specification
+import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
+import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
+import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
+
+
@SpringBootTest
@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiRestClient])
class DmiRestClientSpec extends Specification {
@@ -44,14 +50,32 @@ class DmiRestClientSpec extends Specification {
DmiRestClient objectUnderTest
def resourceUrl = 'some url'
+ def mockResponseEntity = Mock(ResponseEntity)
+
def 'DMI POST operation with JSON.'() {
given: 'the rest template returns a valid response entity'
- def mockResponseEntity = Mock(ResponseEntity)
mockRestTemplate.postForEntity(resourceUrl, _ as HttpEntity, Object.class) >> mockResponseEntity
when: 'POST operation is invoked'
- def result = objectUnderTest.postOperationWithJsonData(resourceUrl, 'json-data')
+ def result = objectUnderTest.postOperationWithJsonData(resourceUrl, 'json-data', READ)
then: 'the output of the method is equal to the output from the test template'
result == mockResponseEntity
}
+ def 'Failing DMI POST operation.'() {
+ given: 'the rest template returns a valid response entity'
+ def serverResponse = 'server response'.getBytes()
+ def httpServerErrorException = new HttpServerErrorException(HttpStatus.FORBIDDEN, 'status text', serverResponse, null)
+ mockRestTemplate.postForEntity(*_) >> { throw httpServerErrorException }
+ when: 'POST operation is invoked'
+ def result = objectUnderTest.postOperationWithJsonData('some url', 'some json', operation)
+ then: 'a Http Client Exception is thrown'
+ def thrown = thrown(HttpClientRequestException)
+ and: 'the exception has the relevant details from the error response'
+ assert thrown.httpStatus == 403
+ assert thrown.message == "Unable to ${operation} resource data."
+ assert thrown.details == 'server response'
+ where: 'the following operation is executed'
+ operation << [CREATE, READ, PATCH]
+ }
+
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
index 2a19df1723..b7ebf2965a 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiDataOperationsSpec.groovy
@@ -30,12 +30,12 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
-import org.springframework.util.MultiValueMap
import spock.lang.Shared
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
+import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
import org.springframework.http.HttpStatus
@@ -63,7 +63,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
and: 'a positive response from DMI service when it is called with the expected parameters'
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
def expectedUrl = dmiServiceBaseUrl + "${expectedDatastoreInUrl}?resourceIdentifier=${resourceIdentifier}${expectedOptionsInUrl}"
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, READ) >> responseFromDmi
dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
when: 'get resource data is invoked'
def result = objectUnderTest.getResourceDataFromDmi(cmHandleId, resourceIdentifier,
@@ -88,7 +88,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def expectedJson = '{"operation":"' + expectedOperationInUrl + '","dataType":"some data type","data":"requestData","cmHandleProperties":{"prop1":"val1"}}'
def responseFromDmi = new ResponseEntity<Object>(HttpStatus.OK)
dmiServiceUrlBuilder.getDmiDatastoreUrl(_, _) >> expectedUrl
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson) >> responseFromDmi
+ mockDmiRestClient.postOperationWithJsonData(expectedUrl, expectedJson, operation) >> responseFromDmi
when: 'write resource method is invoked'
def result = objectUnderTest.writeResourceDataPassThroughRunningFromDmi(cmHandleId, 'parent/child', operation, 'requestData', 'some data type')
then: 'the result is the response from the DMI service'
@@ -98,4 +98,4 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
CREATE || 'create'
UPDATE || 'update'
}
-} \ No newline at end of file
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
index 574f609e9e..ed8f08698d 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiModelOperationsSpec.groovy
@@ -24,7 +24,6 @@ package org.onap.cps.ncmp.api.impl.operations
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
-import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
import org.spockframework.spring.SpringBean
@@ -33,9 +32,10 @@ import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
-import org.springframework.web.util.UriComponentsBuilder
import spock.lang.Shared
+import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.READ
+
@SpringBootTest
@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiModelOperations])
class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
@@ -56,7 +56,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
def moduleReferencesAsLisOfMaps = [[moduleName: 'mod1', revision: 'A'], [moduleName: 'mod2', revision: 'X']]
def expectedUrl = "${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules"
def responseFromDmi = new ResponseEntity([schemas: moduleReferencesAsLisOfMaps], HttpStatus.OK)
- mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{}}')
+ mockDmiRestClient.postOperationWithJsonData(expectedUrl, '{"cmHandleProperties":{}}', READ)
>> responseFromDmi
when: 'get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
@@ -89,7 +89,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
and: 'a positive response from DMI service when it is called with tha expected parameters'
def responseFromDmi = new ResponseEntity<String>(HttpStatus.OK)
mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/modules",
- '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}') >> responseFromDmi
+ '{"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
when: 'a get module references is called'
def result = objectUnderTest.getModuleReferences(yangModelCmHandle)
then: 'the result is the response from DMI service'
@@ -108,7 +108,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
[moduleName: 'mod2', revision: 'C', yangSource: 'other yang source']], HttpStatus.OK)
def expectedModuleReferencesInRequest = '{"name":"mod1","revision":"A"},{"name":"mod2","revision":"X"}'
mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
- '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}') >> responseFromDmi
+ '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":{}}', READ) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, newModuleReferences)
then: 'the result has the 2 expected yang (re)sources (order is not guaranteed)'
@@ -140,7 +140,7 @@ class DmiModelOperationsSpec extends DmiOperationsBaseSpec {
and: 'a positive response from DMI service when it is called with the expected parameters'
def responseFromDmi = new ResponseEntity<>([[moduleName: 'mod1', revision: 'A', yangSource: 'some yang source']], HttpStatus.OK)
mockDmiRestClient.postOperationWithJsonData("${dmiServiceName}/dmi/v1/ch/${cmHandleId}/moduleResources",
- '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":'+expectedAdditionalPropertiesInRequest+'}') >> responseFromDmi
+ '{"data":{"modules":[' + expectedModuleReferencesInRequest + ']},"cmHandleProperties":' + expectedAdditionalPropertiesInRequest + '}', READ) >> responseFromDmi
when: 'get new yang resources from DMI service'
def result = objectUnderTest.getNewYangResourcesFromDmi(yangModelCmHandle, unknownModuleReferences)
then: 'the result is the response from DMI service'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
index dae2bcc0ae..193b94d264 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
@@ -25,6 +25,7 @@ import org.onap.cps.ncmp.api.impl.client.DmiRestClient
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
import org.spockframework.spring.SpringBean
import spock.lang.Shared
import spock.lang.Specification
@@ -38,7 +39,7 @@ abstract class DmiOperationsBaseSpec extends Specification {
DmiRestClient mockDmiRestClient = Mock()
@SpringBean
- YangModelCmHandleRetriever mockCmHandlePropertiesRetriever = Mock()
+ InventoryPersistence mockInventoryPersistence = Mock()
@SpringBean
ObjectMapper spyObjectMapper = Spy()
@@ -56,6 +57,6 @@ abstract class DmiOperationsBaseSpec extends Specification {
yangModelCmHandle.dmiServiceName = dmiServiceName
yangModelCmHandle.dmiProperties = dmiProperties
yangModelCmHandle.id = cmHandleId
- mockCmHandlePropertiesRetriever.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle
+ mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy
new file mode 100644
index 0000000000..d6f4ba6ede
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateBuilderSpec.groovy
@@ -0,0 +1,66 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Bell Canada
+ * 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.spi.model.DataNode
+import org.onap.cps.spi.model.DataNodeBuilder
+import spock.lang.Specification
+
+import java.time.OffsetDateTime
+import java.time.ZoneOffset
+import java.time.format.DateTimeFormatter
+
+class CompositeStateBuilderSpec extends Specification {
+
+ def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
+ .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
+
+ def static cmHandleId = 'myHandle1'
+ def static cmHandleXpath = "/dmi-registry/cm-handles[@id='${cmHandleId}/state']"
+ def static stateDataNodes = [new DataNodeBuilder().withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/lock-reason")
+ .withLeaves(['reason': 'LOCKED_MISBEHAVING', 'details': 'lock details']).build(),
+ new DataNodeBuilder().withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/datastores")
+ .withChildDataNodes(Arrays.asList(new DataNodeBuilder()
+ .withXpath("/dmi-registry/cm-handles[@id='${cmHandleId}']/state/datastores/operational")
+ .withLeaves(['sync-state': 'UNSYNCHRONIZED']).build())).build()]
+ def static cmHandleDataNode = new DataNode(xpath: cmHandleXpath, childDataNodes: stateDataNodes, leaves: ['cm-handle-state': 'ADVISED'])
+
+ def "Composite State Specification"() {
+ when: 'using composite state builder '
+ def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.ADVISED)
+ .withLockReason(LockReasonCategory.LOCKED_MISBEHAVING,"").withOperationalDataStores("UNSYNCHRONIZED",
+ formattedDateAndTime.toString()).withLastUpdatedTime(formattedDateAndTime).build()
+ then: 'it matches expected cm handle state and data store sync state'
+ assert compositeState.cmHandleState == CmHandleState.ADVISED
+ assert compositeState.dataStores.operationalDataStore.syncState == 'UNSYNCHRONIZED'
+ }
+
+ def "Build composite state from DataNode "() {
+ given: "a Data Node "
+ new DataNode(leaves: ['cm-handle-state': 'ADVISED'])
+ when: 'build from data node function is invoked'
+ def compositeState = new CompositeStateBuilder().fromDataNode(cmHandleDataNode).build()
+ then: 'it matches expected state model as JSON'
+ assert compositeState.cmHandleState == CmHandleState.ADVISED
+ }
+
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy
index 4f4cccfe74..5387fc675f 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CompositeStateSpec.groovy
@@ -28,21 +28,20 @@ import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import static CompositeState.DataStores
-import static CompositeState.LockReason
import static CompositeState.Operational
-import static CompositeState.Running
import static org.onap.cps.ncmp.utils.TestUtils.getResourceFileContent
import static org.springframework.util.StringUtils.trimAllWhitespace
class CompositeStateSpec extends Specification {
- def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(OffsetDateTime.of(2022, 1, 1, 1, 1, 1, 1, ZoneOffset.MIN))
+ def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
+ .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
def objectMapper = new ObjectMapper()
def "Composite State Specification"() {
given: "a Composite State"
- def compositeState = new CompositeState(cmhandleState: CmHandleState.ADVISED,
- lockReason: LockReason.builder().reason('lock-reason').details("lock-misbehaving-details").build(),
+ def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
+ lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MISBEHAVING).details("lock misbehaving details").build(),
lastUpdateTime: formattedDateAndTime.toString(),
dataSyncEnabled: false,
dataStores: dataStores())
@@ -56,8 +55,6 @@ class CompositeStateSpec extends Specification {
def dataStores() {
DataStores.builder().operationalDataStore(Operational.builder()
.syncState('NONE_REQUESTED')
- .lastSyncTime(formattedDateAndTime.toString()).build()).runningDataStore(Running.builder()
- .syncState('NONE_REQUESTED')
.lastSyncTime(formattedDateAndTime.toString()).build())
.build()
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy
index 5ecc8b0da3..b638eecd41 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceSpec.groovy
@@ -1,6 +1,6 @@
/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021-2022 Nordix Foundation
+ * ============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.
@@ -18,22 +18,39 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ncmp.api.impl.operations
+package org.onap.cps.ncmp.api.inventory
+import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.api.CpsDataService
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.spi.CpsDataPersistenceService
+import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.DataValidationException
+import org.onap.cps.spi.model.DataNode
+import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
+import spock.lang.Specification
+
+import java.time.OffsetDateTime
+import java.time.ZoneOffset
+import java.time.format.DateTimeFormatter
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
-import org.onap.cps.spi.model.DataNode
-import spock.lang.Specification
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
-class YangModelCmHandleRetrieverSpec extends Specification {
+class InventoryPersistenceSpec extends Specification {
+
+ def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
def mockCpsDataService = Mock(CpsDataService)
- def objectUnderTest = new YangModelCmHandleRetriever(mockCpsDataService)
+ def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
+
+
+ def objectUnderTest = new InventoryPersistence(spiedJsonObjectMapper, mockCpsDataService, mockCpsDataPersistenceService)
+
+ def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
+ .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
def cmHandleId = 'some-cm-handle'
def leaves = ["dmi-service-name":"common service name","dmi-data-service-name":"data service name","dmi-model-service-name":"model service name"]
@@ -49,6 +66,9 @@ class YangModelCmHandleRetrieverSpec extends Specification {
@Shared
def childDataNodesForCmHandleWithPublicProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
+ @Shared
+ def childDataNodesForCmHandleWithState = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/state", leaves: ['cm-handle-state': 'ADVISED'])]
+
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)
@@ -63,12 +83,15 @@ class YangModelCmHandleRetrieverSpec extends Specification {
and: 'the expected DMI properties'
result.dmiProperties == expectedDmiProperties
result.publicProperties == expectedPublicProperties
+ and: 'the state details are returned'
+ result.compositeState.cmHandleState == expectedCompositeState
where: 'the following parameters are used'
- scenario | childDataNodes || expectedDmiProperties || expectedPublicProperties
- 'no properties' | [] || [] || []
- 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")]
- 'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || []
- 'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")]
+ scenario | childDataNodes || expectedDmiProperties || expectedPublicProperties || expectedCompositeState
+ 'no properties' | [] || [] || [] || null
+ 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")] || null
+ 'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || [] || null
+ 'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")] || null
+ 'with state details' | childDataNodesForCmHandleWithState || [] || [] || CmHandleState.ADVISED
}
def "Retrieve CmHandle using datanode with invalid CmHandle id."() {
@@ -91,4 +114,45 @@ class YangModelCmHandleRetrieverSpec extends Specification {
result.dmiDataServiceName == null
result.dmiModelServiceName == null
}
+
+ def 'Get a Cm Handle Composite State'() {
+ given: 'a valid cm handle id'
+ def cmHandleId = 'Some-Cm-Handle'
+ def dataNode = new DataNode(leaves: ['cm-handle-state': 'ADVISED'])
+ and: 'cps data service returns a valid data node'
+ mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
+ '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']/state', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
+ when: 'get cm handle state is invoked'
+ def result = objectUnderTest.getCmHandleState(cmHandleId)
+ then: 'result has returned the correct cm handle state'
+ result.cmHandleState == CmHandleState.ADVISED
+ }
+
+ def 'Update Cm Handle with #scenario State'() {
+ given: 'a cm handle and a composite state'
+ def cmHandleId = 'Some-Cm-Handle'
+ def compositeState = new CompositeState(cmHandleState: cmHandleState, lastUpdateTime: formattedDateAndTime)
+ when: 'update cm handle state is invoked with the #scenario state'
+ objectUnderTest.saveCmHandleState(cmHandleId, compositeState)
+ then: 'update node leaves is invoked with the correct params'
+ 1 * mockCpsDataService.replaceNodeTree('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry/cm-handles[@id=\'Some-Cm-Handle\']', expectedJsonData, _ as OffsetDateTime)
+ where: 'the following states are used'
+ scenario | cmHandleState || expectedJsonData
+ 'READY' | CmHandleState.READY || '{"state":{"cm-handle-state":"READY","last-update-time":"2022-12-31T20:30:40.000+0000"}}'
+ 'LOCKED' | CmHandleState.LOCKED || '{"state":{"cm-handle-state":"LOCKED","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'
+ def dataNodes = [new DataNode()]
+ mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry',
+ '//state[@cm-handle-state="ADVISED"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> dataNodes
+ 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 == dataNodes
+ }
+
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/CmHandleStateSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/CmHandleStateSpec.groovy
deleted file mode 100644
index bfc5c6fa39..0000000000
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/CmHandleStateSpec.groovy
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * ============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.sync
-
-import org.onap.cps.ncmp.api.inventory.CmHandleState
-import spock.lang.Specification
-
-class CmHandleStateSpec extends Specification{
-
- def 'Transition to READY state from ADVISED state'() {
- given: 'a cm handle with an ADVISED state'
- def cmHandleState = CmHandleState.ADVISED
- when: 'the state transitions to the READY state'
- cmHandleState = CmHandleState.READY
- then: 'the cm handle state changes to READY'
- assert CmHandleState.READY == cmHandleState
- }
-
- def 'Transition to READY state from READY state'() {
- given: 'a cm handle with a READY state'
- def cmHandleState = CmHandleState.READY
- when: 'the state transitions to READY state'
- cmHandleState = CmHandleState.READY
- then: 'the cm handle state remains as READY'
- assert CmHandleState.READY == cmHandleState
- }
-
-}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy
index 35de99fefb..bcfe47fd5d 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncSpec.groovy
@@ -1,5 +1,5 @@
/*
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* Copyright (C) 2022 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,40 +20,72 @@
package org.onap.cps.ncmp.api.inventory.sync
-
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
import org.onap.cps.ncmp.api.inventory.CmHandleState
import org.onap.cps.ncmp.api.inventory.CompositeState
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
+import org.onap.cps.ncmp.api.inventory.LockReasonCategory
import spock.lang.Specification
class ModuleSyncSpec extends Specification {
+ def mockInventoryPersistence = Mock(InventoryPersistence)
+
def mockSyncUtils = Mock(SyncUtils)
def mockModuleSyncService = Mock(ModuleSyncService)
def cmHandleState = CmHandleState.ADVISED
- def objectUnderTest = new ModuleSyncWatchdog(mockSyncUtils, mockModuleSyncService)
+ def objectUnderTest = new ModuleSyncWatchdog(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService)
def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handles'() {
given: 'cm handles in an advised state'
- def compositeState = new CompositeState()
- compositeState.cmhandleState = cmHandleState
- def yangModelCmHandle1 = new YangModelCmHandle(compositeState: compositeState)
- def yangModelCmHandle2 = new YangModelCmHandle(compositeState: compositeState)
+ def compositeState1 = new CompositeState(cmHandleState: cmHandleState)
+ def compositeState2 = new CompositeState(cmHandleState: cmHandleState)
+ def yangModelCmHandle1 = new YangModelCmHandle(id: 'some-cm-handle', compositeState: compositeState1)
+ def yangModelCmHandle2 = new YangModelCmHandle(id: 'some-cm-handle-2', compositeState: compositeState2)
and: 'sync utilities return a cm handle twice'
mockSyncUtils.getAnAdvisedCmHandle() >>> [yangModelCmHandle1, yangModelCmHandle2, null]
when: 'module sync poll is executed'
objectUnderTest.executeAdvisedCmHandlePoll()
- then: 'module sync service syncs the first cm handle and creates a schema set'
+ then: 'the inventory persistence cm handle returns a composite state for the first cm handle'
+ 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle') >> compositeState1
+ and: 'module sync service syncs the first cm handle and creates a schema set'
1 * mockModuleSyncService.syncAndCreateSchemaSet(yangModelCmHandle1)
- and: 'the first cm handle is updated to state "READY" from "ADVISED"'
- 1 * mockSyncUtils.updateCmHandleState(yangModelCmHandle1, CmHandleState.READY)
- then: 'module sync service syncs the second cm handle and creates a schema set'
+ and: 'the composite state cm handle state is now READY'
+ assert compositeState1.getCmHandleState() == CmHandleState.READY
+ and: 'the first cm handle state is updated'
+ 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle', compositeState1)
+ then: 'the inventory persistence cm handle returns a composite state for the second cm handle'
+ mockInventoryPersistence.getCmHandleState('some-cm-handle-2') >> compositeState2
+ and: 'module sync service syncs the second cm handle and creates a schema set'
1 * mockModuleSyncService.syncAndCreateSchemaSet(yangModelCmHandle2)
- then: 'the second cm handle is updated to state "READY" from "ADVISED"'
- 1 * mockSyncUtils.updateCmHandleState(yangModelCmHandle2, CmHandleState.READY)
+ and: 'the composite state cm handle state is now READY'
+ assert compositeState2.getCmHandleState() == CmHandleState.READY
+ and: 'the second cm handle state is updated'
+ 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle-2', compositeState2)
+ }
+
+ def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handle with failure'() {
+ given: 'cm handles in an advised state'
+ def compositeState = new CompositeState(cmHandleState: cmHandleState)
+ def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', compositeState: compositeState)
+ and: 'sync utilities return a cm handle'
+ mockSyncUtils.getAnAdvisedCmHandle() >>> [yangModelCmHandle, null]
+ when: 'module sync poll is executed'
+ objectUnderTest.executeAdvisedCmHandlePoll()
+ then: 'the inventory persistence cm handle returns a composite state for the cm handle'
+ 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle') >> compositeState
+ and: 'module sync service attempts to sync the cm handle and throws an exception'
+ 1 * mockModuleSyncService.syncAndCreateSchemaSet(*_) >> { throw new Exception('some exception') }
+ and: 'the composite state cm handle state is now LOCKED'
+ assert compositeState.getCmHandleState() == CmHandleState.LOCKED
+ and: 'update lock reason, details and attempts is invoked'
+ 1 * mockSyncUtils.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MISBEHAVING ,'some exception')
+ and: 'the cm handle state is updated'
+ 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle', compositeState)
+
}
}
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 c80263ef05..7d67acccc3 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
@@ -20,29 +20,22 @@
package org.onap.cps.ncmp.api.inventory.sync
-import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.api.CpsDataService
-import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever
-import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
import org.onap.cps.ncmp.api.inventory.CmHandleState
import org.onap.cps.ncmp.api.inventory.CompositeState
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
+import org.onap.cps.ncmp.api.inventory.LockReasonCategory
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.model.DataNode
-import org.onap.cps.utils.JsonObjectMapper
import spock.lang.Shared
import spock.lang.Specification
-import java.time.OffsetDateTime
-
class SyncUtilsSpec extends Specification{
- def mockCpsDataService = Mock(CpsDataService)
def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
- def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
- def mockYangModelCmHandleRetriever = Mock(YangModelCmHandleRetriever)
+ def mockInventoryPersistence = Mock(InventoryPersistence)
- def objectUnderTest = new SyncUtils(mockCpsDataService, mockCpsDataPersistenceService, spiedJsonObjectMapper, mockYangModelCmHandleRetriever)
+ def objectUnderTest = new SyncUtils(mockInventoryPersistence)
@Shared
def dataNode = new DataNode(leaves: ['id': 'cm-handle-123'])
@@ -50,16 +43,14 @@ class SyncUtilsSpec extends Specification{
def 'Get an advised Cm-Handle where ADVISED cm handle #scenario'() {
- given: 'the cps (persistence service) returns a collection of data nodes'
- mockCpsDataPersistenceService.queryDataNodes('NCMP-Admin',
- 'ncmp-dmi-registry', '//cm-handles[@state=\"ADVISED\"]',
- FetchDescendantsOption.OMIT_DESCENDANTS) >> dataNodeCollection
+ given: 'the inventory persistence service returns a collection of data nodes'
+ mockInventoryPersistence.getCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection
when: 'get advised cm handle is called'
objectUnderTest.getAnAdvisedCmHandle()
then: 'the returned data node collection is the correct size'
dataNodeCollection.size() == expectedDataNodeSize
and: 'get yang model cm handles is invoked the correct number of times'
- expectedCallsToGetYangModelCmHandle * mockYangModelCmHandleRetriever.getYangModelCmHandle('cm-handle-123')
+ expectedCallsToGetYangModelCmHandle * mockInventoryPersistence.getYangModelCmHandle('cm-handle-123')
where: 'the following scenarios are used'
scenario | dataNodeCollection || expectedCallsToGetYangModelCmHandle | expectedDataNodeSize
'exists' | [ dataNode ] || 1 | 1
@@ -67,16 +58,18 @@ class SyncUtilsSpec extends Specification{
}
- def 'Update cm handle state from Advised to Ready'() {
- given: 'a yang model cm handle and the expected json data'
- def compositeState = new CompositeState()
- compositeState.cmhandleState = CmHandleState.ADVISED
- def yangModelCmHandle = new YangModelCmHandle(id: 'Some-Cm-Handle', compositeState: compositeState )
- def expectedJsonData = '{"cm-handles":[{"id":"Some-Cm-Handle","state":{"cm-handle-state":"READY"}}]}'
- when: 'update cm handle state is called'
- objectUnderTest.updateCmHandleState(yangModelCmHandle, CmHandleState.READY)
- then: 'update data note leaves is invoked with the correct params'
- 1 * mockCpsDataService.updateNodeLeaves('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', expectedJsonData, _ as OffsetDateTime)
+ def 'Update Lock Reason, Details and Attempts where lock reason #scenario'() {
+ given: 'A locked state'
+ def compositeState = new CompositeState(lockReason: lockReason)
+ when: 'update cm handle details and attempts is called'
+ objectUnderTest.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MISBEHAVING, 'new error message')
+ then: 'the composite state lock reason and details are updated'
+ assert compositeState.lockReason.lockReasonCategory == LockReasonCategory.LOCKED_MISBEHAVING
+ assert compositeState.lockReason.details == expectedDetails
+ where:
+ scenario | lockReason || expectedDetails
+ 'does not exist' | null || 'Attempt #1 failed: new error message'
+ 'exists' | CompositeState.LockReason.builder().details("Attempt #2 failed: some error message").build() || 'Attempt #3 failed: new error message'
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
index 4c8dcace7d..964826be13 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
@@ -45,14 +45,14 @@ class DmiServiceUrlBuilderSpec extends Specification {
def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
"cmHandle", PASSTHROUGH_RUNNING)
and: 'query params'
- def uriQueries = objectUnderTest.populateQueryParams(resourceId,
- 'optionsParamInQuery', topicParamInQuery)
+ def uriQueries = objectUnderTest.populateQueryParams(resourceId,
+ 'optionsParamInQuery', topic)
when: 'a dmi datastore service url is generated'
def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
then: 'service url is generated as expected'
assert dmiServiceUrl == expectedDmiServiceUrl
where: 'the following parameters are used'
- scenario | topicParamInQuery | resourceId || expectedDmiServiceUrl
+ scenario | topic | resourceId || expectedDmiServiceUrl
'With valid resourceId' | 'topicParamInQuery' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery&topic=topicParamInQuery'
'With Empty resourceId' | 'topicParamInQuery' | '' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?options=optionsParamInQuery&topic=topicParamInQuery'
'With Empty dmi base path' | 'topicParamInQuery' | 'resourceId' || 'dmiServiceName/dmi/v1/ch/cmHandle/data/ds/ncmp-datastore:passthrough-running?resourceIdentifier=resourceId&options=optionsParamInQuery&topic=topicParamInQuery'