Merge "Normalize parent xpath when building datanodes in CpsDataService"
[cps.git] / cps-ncmp-service / src / test / groovy / org / onap / cps / ncmp / api / impl / events / avcsubscription / SubscriptionEventResponseConsumerSpec.groovy
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (c) 2023 Nordix Foundation.
4  *  ================================================================================
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an 'AS IS' BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.ncmp.api.impl.events.avcsubscription
22
23 import com.fasterxml.jackson.databind.ObjectMapper
24 import com.hazelcast.map.IMap
25 import org.apache.kafka.clients.consumer.ConsumerRecord
26 import org.onap.cps.ncmp.api.impl.subscriptions.SubscriptionPersistenceImpl
27 import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
28 import org.onap.cps.ncmp.api.models.SubscriptionEventResponse
29 import org.onap.cps.spi.model.DataNodeBuilder
30 import org.onap.cps.utils.JsonObjectMapper
31 import org.springframework.boot.test.context.SpringBootTest
32
33 @SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
34 class SubscriptionEventResponseConsumerSpec extends MessagingBaseSpec {
35
36     IMap<String, Set<String>> mockForwardedSubscriptionEventCache = Mock(IMap<String, Set<String>>)
37     def mockSubscriptionPersistence = Mock(SubscriptionPersistenceImpl)
38     def mockSubscriptionEventResponseMapper  = Mock(SubscriptionEventResponseMapper)
39     def mockSubscriptionEventResponseOutcome = Mock(SubscriptionEventResponseOutcome)
40
41     def objectUnderTest = new SubscriptionEventResponseConsumer(mockForwardedSubscriptionEventCache,
42         mockSubscriptionPersistence, mockSubscriptionEventResponseMapper, mockSubscriptionEventResponseOutcome)
43
44     def cmHandleToStatusMap = [CMHandle1: 'PENDING', CMHandle2: 'ACCEPTED'] as Map
45     def testEventReceived = new SubscriptionEventResponse(clientId: 'some-client-id',
46         subscriptionName: 'some-subscription-name', dmiName: 'some-dmi-name', cmHandleIdToStatus: cmHandleToStatusMap)
47     def consumerRecord = new ConsumerRecord<String, SubscriptionEventResponse>('topic-name', 0, 0, 'event-key', testEventReceived)
48
49     def 'Consume Subscription Event Response where all DMIs have responded'() {
50         given: 'a subscription event response and notifications are enabled'
51             objectUnderTest.notificationFeatureEnabled = isNotificationFeatureEnabled
52         and: 'subscription model loader is enabled'
53             objectUnderTest.subscriptionModelLoaderEnabled = true
54         and: 'a data node exist in db'
55             def leaves1 = [status:'ACCEPTED', cmHandleId:'cmhandle1'] as Map
56             def dataNode = new DataNodeBuilder().withDataspace('NCMP-Admin')
57                 .withAnchor('AVC-Subscriptions').withXpath('/subscription-registry/subscription')
58                 .withLeaves(leaves1).build()
59         and: 'subscription persistence service returns data node'
60             mockSubscriptionPersistence.getCmHandlesForSubscriptionEvent(*_) >> [dataNode]
61         when: 'the valid event is consumed'
62             objectUnderTest.consumeSubscriptionEventResponse(consumerRecord)
63         then: 'the forwarded subscription event cache returns only the received dmiName existing for the subscription create event'
64             1 * mockForwardedSubscriptionEventCache.containsKey('some-client-idsome-subscription-name') >> true
65             1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> (['some-dmi-name'] as Set)
66         and: 'the forwarded subscription event cache returns an empty Map when the dmiName has been removed'
67             1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> ([] as Set)
68         and: 'the subscription event is removed from the map'
69             numberOfExpectedCallToRemove * mockForwardedSubscriptionEventCache.remove('some-client-idsome-subscription-name')
70         and: 'a response outcome has been created'
71             numberOfExpectedCallToSendResponse * mockSubscriptionEventResponseOutcome.sendResponse('some-client-id', 'some-subscription-name')
72         where: 'the following values are used'
73             scenario             | isNotificationFeatureEnabled  ||  numberOfExpectedCallToRemove  || numberOfExpectedCallToSendResponse
74             'Response sent'      | true                          ||   1                            || 1
75             'Response not sent'  | false                         ||   0                            || 0
76     }
77
78     def 'Consume Subscription Event Response where another DMI has not yet responded'() {
79         given: 'a subscription event response and notifications are enabled'
80             objectUnderTest.notificationFeatureEnabled = true
81         and: 'subscription model loader is enabled'
82             objectUnderTest.subscriptionModelLoaderEnabled = true
83         when: 'the valid event is consumed'
84             objectUnderTest.consumeSubscriptionEventResponse(consumerRecord)
85         then: 'the forwarded subscription event cache returns only the received dmiName existing for the subscription create event'
86             1 * mockForwardedSubscriptionEventCache.containsKey('some-client-idsome-subscription-name') >> true
87             1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> (['some-dmi-name', 'non-responded-dmi'] as Set)
88         and: 'the forwarded subscription event cache returns an empty Map when the dmiName has been removed'
89             1 * mockForwardedSubscriptionEventCache.get('some-client-idsome-subscription-name') >> (['non-responded-dmi'] as Set)
90         and: 'the subscription event is not removed from the map'
91             0 * mockForwardedSubscriptionEventCache.remove(_)
92         and: 'a response outcome has not been created'
93             0 * mockSubscriptionEventResponseOutcome.sendResponse(*_)
94     }
95
96     def 'Update subscription event when the model loader flag is enabled'() {
97         given: 'subscription model loader is enabled as per #scenario'
98             objectUnderTest.subscriptionModelLoaderEnabled = isSubscriptionModelLoaderEnabled
99         when: 'the valid event is consumed'
100             objectUnderTest.consumeSubscriptionEventResponse(consumerRecord)
101         then: 'the forwarded subscription event cache does not return dmiName for the subscription create event'
102             1 * mockForwardedSubscriptionEventCache.containsKey('some-client-idsome-subscription-name') >> false
103         and: 'the mapper returns yang model subscription event with #numberOfExpectedCall'
104             numberOfExpectedCall * mockSubscriptionEventResponseMapper.toYangModelSubscriptionEvent(_)
105         and: 'subscription event has been updated into DB with #numberOfExpectedCall'
106             numberOfExpectedCall * mockSubscriptionPersistence.saveSubscriptionEvent(_)
107         where: 'the following values are used'
108             scenario                   | isSubscriptionModelLoaderEnabled || numberOfExpectedCall
109             'The event is updated'     | true                             || 1
110             'The event is not updated' | false                            || 0
111     }
112 }