Subscription Creation: NCMP to Client CloudEvent transformation
[cps.git] / cps-ncmp-service / src / test / groovy / org / onap / cps / ncmp / api / impl / events / avcsubscription / SubscriptionEventResponseConsumerSpec.groovy
index 5355dd8..7cc40cc 100644 (file)
@@ -22,17 +22,27 @@ package org.onap.cps.ncmp.api.impl.events.avcsubscription
 
 import com.fasterxml.jackson.databind.ObjectMapper
 import com.hazelcast.map.IMap
+import io.cloudevents.CloudEvent
+import io.cloudevents.core.builder.CloudEventBuilder
 import org.apache.kafka.clients.consumer.ConsumerRecord
 import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistenceImpl
 import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
-import org.onap.cps.ncmp.api.models.SubscriptionEventResponse
+import org.onap.cps.ncmp.events.avcsubscription1_0_0.dmi_to_ncmp.SubscriptionEventResponse
+import org.onap.cps.ncmp.utils.TestUtils
 import org.onap.cps.spi.model.DataNodeBuilder
 import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 
 @SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
 class SubscriptionEventResponseConsumerSpec extends MessagingBaseSpec {
 
+    @Autowired
+    JsonObjectMapper jsonObjectMapper
+
+    @Autowired
+    ObjectMapper objectMapper
+
     IMap<String, Set<String>> mockForwardedSubscriptionEventCache = Mock(IMap<String, Set<String>>)
     def mockSubscriptionPersistence = Mock(SubscriptionPersistenceImpl)
     def mockSubscriptionEventResponseMapper  = Mock(SubscriptionEventResponseMapper)
@@ -41,72 +51,90 @@ class SubscriptionEventResponseConsumerSpec extends MessagingBaseSpec {
     def objectUnderTest = new SubscriptionEventResponseConsumer(mockForwardedSubscriptionEventCache,
         mockSubscriptionPersistence, mockSubscriptionEventResponseMapper, mockSubscriptionEventResponseOutcome)
 
-    def cmHandleToStatusMap = [CMHandle1: 'PENDING', CMHandle2: 'ACCEPTED'] as Map
-    def testEventReceived = new SubscriptionEventResponse(clientId: 'some-client-id',
-        subscriptionName: 'some-subscription-name', dmiName: 'some-dmi-name', cmHandleIdToStatus: cmHandleToStatusMap)
-    def consumerRecord = new ConsumerRecord<String, SubscriptionEventResponse>('topic-name', 0, 0, 'event-key', testEventReceived)
-
     def 'Consume Subscription Event Response where all DMIs have responded'() {
-        given: 'a subscription event response and notifications are enabled'
-            objectUnderTest.notificationFeatureEnabled = isNotificationFeatureEnabled
+        given: 'a consumer record including cloud event having subscription response'
+            def consumerRecordWithCloudEventAndSubscriptionResponse = getConsumerRecord()
+        and: 'a subscription response event'
+            def subscriptionResponseEvent = getSubscriptionResponseEvent()
+        and: 'a subscription event response and notifications are enabled'
+            objectUnderTest.notificationFeatureEnabled = notificationEnabled
         and: 'subscription model loader is enabled'
-            objectUnderTest.subscriptionModelLoaderEnabled = true
-        and: 'a data node exist in db'
-            def leaves1 = [status:'ACCEPTED', cmHandleId:'cmhandle1'] as Map
-            def dataNode = new DataNodeBuilder().withDataspace('NCMP-Admin')
-                .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
-                .withLeaves(leaves1).build()
-        and: 'subscription persistence service returns data node'
-            mockSubscriptionPersistence.getCmHandlesForSubscriptionEvent(*_) >> [dataNode]
+            objectUnderTest.subscriptionModelLoaderEnabled = modelLoaderEnabled
+        and: 'subscription persistence service returns data node includes no pending cm handle'
+            mockSubscriptionPersistence.getCmHandlesForSubscriptionEvent(*_) >> [getDataNode()]
         when: 'the valid event is consumed'
-            objectUnderTest.consumeSubscriptionEventResponse(consumerRecord)
+            objectUnderTest.consumeSubscriptionEventResponse(consumerRecordWithCloudEventAndSubscriptionResponse)
         then: 'the forwarded subscription event cache returns only the received dmiName existing for the subscription create event'
-            1 * mockForwardedSubscriptionEventCache.containsKey('some-client-idsome-subscription-name') >> true
-            1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> (['some-dmi-name'] as Set)
+            1 * mockForwardedSubscriptionEventCache.containsKey('SCO-9989752cm-subscription-001') >> true
+            1 * mockForwardedSubscriptionEventCache.get('SCO-9989752cm-subscription-001') >> (['some-dmi-name'] as Set)
         and: 'the forwarded subscription event cache returns an empty Map when the dmiName has been removed'
-            1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> ([] as Set)
+            1 * mockForwardedSubscriptionEventCache.get('SCO-9989752cm-subscription-001') >> ([] as Set)
+        and: 'the response event is map to yang model'
+            numberOfTimeToPersist * mockSubscriptionEventResponseMapper.toYangModelSubscriptionEvent(_)
+        and: 'the response event is persisted into the db'
+            numberOfTimeToPersist * mockSubscriptionPersistence.saveSubscriptionEvent(_)
         and: 'the subscription event is removed from the map'
-            numberOfExpectedCallToRemove * mockForwardedSubscriptionEventCache.remove('some-client-idsome-subscription-name')
+            numberOfTimeToRemove * mockForwardedSubscriptionEventCache.remove('SCO-9989752cm-subscription-001')
         and: 'a response outcome has been created'
-            numberOfExpectedCallToSendResponse * mockSubscriptionEventResponseOutcome.sendResponse('some-client-id', 'some-subscription-name')
+            numberOfTimeToResponse * mockSubscriptionEventResponseOutcome.sendResponse(subscriptionResponseEvent, 'subscriptionCreated')
         where: 'the following values are used'
-            scenario             | isNotificationFeatureEnabled  ||  numberOfExpectedCallToRemove  || numberOfExpectedCallToSendResponse
-            'Response sent'      | true                          ||   1                            || 1
-            'Response not sent'  | false                         ||   0                            || 0
+            scenario                                              | modelLoaderEnabled  |   notificationEnabled  ||  numberOfTimeToPersist  ||  numberOfTimeToRemove  || numberOfTimeToResponse
+            'Both model loader and notification are enabled'      |    true             |     true               ||   1                     ||      1                 ||       1
+            'Both model loader and notification are disabled'     |    false            |     false              ||   0                     ||      0                 ||       0
+            'Model loader enabled and notification  disabled'     |    true             |     false              ||   1                     ||      0                 ||       0
+            'Model loader disabled and notification enabled'      |    false            |     true               ||   0                     ||      1                 ||       1
     }
 
     def 'Consume Subscription Event Response where another DMI has not yet responded'() {
         given: 'a subscription event response and notifications are enabled'
-            objectUnderTest.notificationFeatureEnabled = true
+            objectUnderTest.notificationFeatureEnabled = notificationEnabled
         and: 'subscription model loader is enabled'
-            objectUnderTest.subscriptionModelLoaderEnabled = true
+            objectUnderTest.subscriptionModelLoaderEnabled = modelLoaderEnabled
         when: 'the valid event is consumed'
-            objectUnderTest.consumeSubscriptionEventResponse(consumerRecord)
+            objectUnderTest.consumeSubscriptionEventResponse(getConsumerRecord())
         then: 'the forwarded subscription event cache returns only the received dmiName existing for the subscription create event'
-            1 * mockForwardedSubscriptionEventCache.containsKey('some-client-idsome-subscription-name') >> true
-            1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> (['some-dmi-name', 'non-responded-dmi'] as Set)
+            1 * mockForwardedSubscriptionEventCache.containsKey('SCO-9989752cm-subscription-001') >> true
+            1 * mockForwardedSubscriptionEventCache.get('SCO-9989752cm-subscription-001') >> (['responded-dmi', 'non-responded-dmi'] as Set)
         and: 'the forwarded subscription event cache returns an empty Map when the dmiName has been removed'
-            1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> (['non-responded-dmi'] as Set)
+            1 * mockForwardedSubscriptionEventCache.get('SCO-9989752cm-subscription-001') >> (['non-responded-dmi'] as Set)
+        and: 'the response event is map to yang model'
+            numberOfTimeToPersist * mockSubscriptionEventResponseMapper.toYangModelSubscriptionEvent(_)
+        and: 'the response event is persisted into the db'
+            numberOfTimeToPersist * mockSubscriptionPersistence.saveSubscriptionEvent(_)
+        and: 'the subscription event is removed from the map'
         and: 'the subscription event is not removed from the map'
             0 * mockForwardedSubscriptionEventCache.remove(_)
         and: 'a response outcome has not been created'
             0 * mockSubscriptionEventResponseOutcome.sendResponse(*_)
+        where: 'the following values are used'
+            scenario                                              | modelLoaderEnabled  |   notificationEnabled  ||  numberOfTimeToPersist
+            'Both model loader and notification are enabled'      |    true             |     true               ||   1
+            'Both model loader and notification are disabled'     |    false            |     false              ||   0
+            'Model loader enabled and notification  disabled'     |    true             |     false              ||   1
+            'Model loader disabled and notification enabled'      |    false            |     true               ||   0
     }
 
-    def 'Update subscription event when the model loader flag is enabled'() {
-        given: 'subscription model loader is enabled as per #scenario'
-            objectUnderTest.subscriptionModelLoaderEnabled = isSubscriptionModelLoaderEnabled
-        when: 'the valid event is consumed'
-            objectUnderTest.consumeSubscriptionEventResponse(consumerRecord)
-        then: 'the forwarded subscription event cache does not return dmiName for the subscription create event'
-            1 * mockForwardedSubscriptionEventCache.containsKey('some-client-idsome-subscription-name') >> false
-        and: 'the mapper returns yang model subscription event with #numberOfExpectedCall'
-            numberOfExpectedCall * mockSubscriptionEventResponseMapper.toYangModelSubscriptionEvent(_)
-        and: 'subscription event has been updated into DB with #numberOfExpectedCall'
-            numberOfExpectedCall * mockSubscriptionPersistence.saveSubscriptionEvent(_)
-        where: 'the following values are used'
-            scenario                   | isSubscriptionModelLoaderEnabled || numberOfExpectedCall
-            'The event is updated'     | true                             || 1
-            'The event is not updated' | false                            || 0
+    def getSubscriptionResponseEvent() {
+        def subscriptionResponseJsonData = TestUtils.getResourceFileContent('avcSubscriptionEventResponse.json')
+        return jsonObjectMapper.convertJsonString(subscriptionResponseJsonData, SubscriptionEventResponse.class)
+    }
+
+    def getCloudEventHavingSubscriptionResponseEvent() {
+        return CloudEventBuilder.v1()
+            .withData(objectMapper.writeValueAsBytes(getSubscriptionResponseEvent()))
+            .withId('some-id')
+            .withType('subscriptionCreated')
+            .withSource(URI.create('NCMP')).build()
+    }
+
+    def getConsumerRecord() {
+        return new ConsumerRecord<String, CloudEvent>('topic-name', 0, 0, 'event-key', getCloudEventHavingSubscriptionResponseEvent())
+    }
+
+    def getDataNode() {
+        def leaves = [status:'ACCEPTED', cmHandleId:'cmhandle1'] as Map
+        return new DataNodeBuilder().withDataspace('NCMP-Admin')
+            .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
+            .withLeaves(leaves).build()
     }
 }