summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src/test/groovy/org/onap
diff options
context:
space:
mode:
authorlukegleeson <luke.gleeson@est.tech>2023-04-06 15:28:56 +0100
committerlukegleeson <luke.gleeson@est.tech>2023-04-28 12:22:37 +0100
commit3c0ea89e2bd77d2f4f86f0729643455e1b29c5ac (patch)
tree689099c10faf6bde751ed8b716a204d7d476bbde /cps-ncmp-service/src/test/groovy/org/onap
parenta4cfede5bac589107ab81968f1d3a88c11a464d2 (diff)
Timeout for Subscription Create Partial Response
- Implemented default 30s timeout for DMI Responses - Placeholders have been TODO'd for Outcome Response generation and Persisted Subscription Updating - Refactored common HazelcastCacheConfig methods - Some tests required a blocking variable due to seperate thread usage Issue-ID: CPS-1599 Signed-off-by: lukegleeson <luke.gleeson@est.tech> Change-Id: I2b1a35e93939daa0524d379ac4736d714ef61a6f
Diffstat (limited to 'cps-ncmp-service/src/test/groovy/org/onap')
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy4
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/ForwardedSubscriptionEventCacheConfigSpec.groovy75
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/SubscriptionEventResponseConsumerSpec.groovy79
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avc/SubscriptionEventMapperSpec.groovy19
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avcsubscription/SubscriptionEventForwarderSpec.groovy38
5 files changed, 206 insertions, 9 deletions
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy
index 6829d834d..567debdde 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationCacheConfigSpec.groovy
@@ -51,8 +51,8 @@ class SynchronizationCacheConfigSpec extends Specification {
assert null != moduleSyncStartedOnCmHandles
and: 'system is able to create an instance of a map to hold data sync semaphores'
assert null != dataSyncSemaphores
- and: 'there 3 instances'
- assert Hazelcast.allHazelcastInstances.size() == 3
+ and: 'there are at least 3 instances'
+ assert Hazelcast.allHazelcastInstances.size() > 2
and: 'they have the correct names (in any order)'
assert Hazelcast.allHazelcastInstances.name.containsAll('moduleSyncWorkQueue', 'moduleSyncStartedOnCmHandles', 'dataSyncSemaphores' )
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/ForwardedSubscriptionEventCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/ForwardedSubscriptionEventCacheConfigSpec.groovy
new file mode 100644
index 000000000..7448daf59
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/ForwardedSubscriptionEventCacheConfigSpec.groovy
@@ -0,0 +1,75 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.event.avc
+
+import com.hazelcast.config.Config
+import com.hazelcast.core.Hazelcast
+import com.hazelcast.map.IMap
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import spock.lang.Specification
+
+@SpringBootTest(classes = [ForwardedSubscriptionEventCacheConfig])
+class ForwardedSubscriptionEventCacheConfigSpec extends Specification {
+
+ @Autowired
+ private IMap<String, Set<String>> forwardedSubscriptionEventCache
+
+ def 'Embedded (hazelcast) cache for Forwarded Subscription Event Cache.'() {
+ expect: 'system is able to create an instance of the Forwarded Subscription Event Cache'
+ assert null != forwardedSubscriptionEventCache
+ and: 'there is at least 1 instance'
+ assert Hazelcast.allHazelcastInstances.size() > 0
+ and: 'Forwarded Subscription Event Cache is present'
+ assert Hazelcast.allHazelcastInstances.name.contains('hazelCastInstanceSubscriptionEvents')
+ }
+
+ def 'Verify configs for Distributed Caches'(){
+ given: 'the Forwarded Subscription Event Cache config'
+ def forwardedSubscriptionEventCacheConfig = Hazelcast.getHazelcastInstanceByName('hazelCastInstanceSubscriptionEvents').config.mapConfigs.get('forwardedSubscriptionEventCacheMapConfig')
+ expect: 'system created instance with correct config'
+ assert forwardedSubscriptionEventCacheConfig.backupCount == 3
+ assert forwardedSubscriptionEventCacheConfig.asyncBackupCount == 3
+ }
+
+ def 'Verify deployment network configs for Distributed Caches'() {
+ given: 'the Forwarded Subscription Event Cache config'
+ def forwardedSubscriptionEventCacheNetworkConfig = Hazelcast.getHazelcastInstanceByName('hazelCastInstanceSubscriptionEvents').config.networkConfig
+ expect: 'system created instance with correct config'
+ assert forwardedSubscriptionEventCacheNetworkConfig.join.autoDetectionConfig.enabled
+ assert !forwardedSubscriptionEventCacheNetworkConfig.join.kubernetesConfig.enabled
+ }
+
+ def 'Verify network config'() {
+ given: 'Synchronization config object and test configuration'
+ def objectUnderTest = new ForwardedSubscriptionEventCacheConfig()
+ def testConfig = new Config()
+ when: 'kubernetes properties are enabled'
+ objectUnderTest.cacheKubernetesEnabled = true
+ objectUnderTest.cacheKubernetesServiceName = 'test-service-name'
+ and: 'method called to update the discovery mode'
+ objectUnderTest.updateDiscoveryMode(testConfig)
+ then: 'applied properties are reflected'
+ assert testConfig.networkConfig.join.kubernetesConfig.enabled
+ assert testConfig.networkConfig.join.kubernetesConfig.properties.get('service-name') == 'test-service-name'
+
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/SubscriptionEventResponseConsumerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/SubscriptionEventResponseConsumerSpec.groovy
new file mode 100644
index 000000000..a67346200
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/avc/SubscriptionEventResponseConsumerSpec.groovy
@@ -0,0 +1,79 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (c) 2023 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an 'AS IS' BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.impl.event.avc
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.hazelcast.map.IMap
+import org.onap.cps.ncmp.api.kafka.MessagingBaseSpec
+import org.onap.cps.ncmp.api.models.SubscriptionEventResponse
+import org.onap.cps.utils.JsonObjectMapper
+import org.springframework.boot.test.context.SpringBootTest
+
+@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
+class SubscriptionEventResponseConsumerSpec extends MessagingBaseSpec {
+
+ IMap<String, Set<String>> mockForwardedSubscriptionEventCache = Mock(IMap<String, Set<String>>)
+
+ def objectUnderTest = new SubscriptionEventResponseConsumer(mockForwardedSubscriptionEventCache)
+
+
+ def 'Consume Subscription Event Response where all DMIs have responded'() {
+ given: 'a subscription event response with a clientId, subscriptionName and dmiName'
+ def testEventReceived = new SubscriptionEventResponse()
+ testEventReceived.clientId = 'some-client-id'
+ testEventReceived.subscriptionName = 'some-subscription-name'
+ testEventReceived.dmiName = 'some-dmi-name'
+ and: 'notifications are enabled'
+ objectUnderTest.notificationFeatureEnabled = true
+ and: 'subscription model loader is enabled'
+ objectUnderTest.subscriptionModelLoaderEnabled = true
+ when: 'the valid event is consumed'
+ objectUnderTest.consumeSubscriptionEventResponse(testEventReceived)
+ 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)
+ 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)
+ and: 'the subscription event is removed from the map'
+ 1 * mockForwardedSubscriptionEventCache.remove('some-client-idsome-subscription-name')
+ }
+
+ def 'Consume Subscription Event Response where another DMI has not yet responded'() {
+ given: 'a subscription event response with a clientId, subscriptionName and dmiName'
+ def testEventReceived = new SubscriptionEventResponse()
+ testEventReceived.clientId = 'some-client-id'
+ testEventReceived.subscriptionName = 'some-subscription-name'
+ testEventReceived.dmiName = 'some-dmi-name'
+ and: 'notifications are enabled'
+ objectUnderTest.notificationFeatureEnabled = true
+ and: 'subscription model loader is enabled'
+ objectUnderTest.subscriptionModelLoaderEnabled = true
+ when: 'the valid event is consumed'
+ objectUnderTest.consumeSubscriptionEventResponse(testEventReceived)
+ 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)
+ 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)
+ and: 'the subscription event is not removed from the map'
+ 0 * mockForwardedSubscriptionEventCache.remove(_)
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avc/SubscriptionEventMapperSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avc/SubscriptionEventMapperSpec.groovy
index 3a7aa481c..f2ff1f7b2 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avc/SubscriptionEventMapperSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avc/SubscriptionEventMapperSpec.groovy
@@ -48,7 +48,7 @@ class SubscriptionEventMapperSpec extends Specification {
def result = objectUnderTest.toYangModelSubscriptionEvent(testEventToMap)
then: 'the resulting yang model subscription event contains the correct clientId'
assert result.clientId == "SCO-9989752"
- and: 'client name'
+ and: 'subscription name'
assert result.subscriptionName == "cm-subscription-001"
and: 'is tagged value is false'
assert !result.isTagged
@@ -60,4 +60,21 @@ class SubscriptionEventMapperSpec extends Specification {
assert result.topic == null
}
+ def 'Map null subscription event to yang model subscription event where #scenario'() {
+ given: 'a new Subscription Event with no data'
+ def testEventToMap = new SubscriptionEvent()
+ when: 'the event is mapped to a yang model subscription'
+ def result = objectUnderTest.toYangModelSubscriptionEvent(testEventToMap)
+ then: 'the resulting yang model subscription event contains null clientId'
+ assert result.clientId == null
+ and: 'subscription name is null'
+ assert result.subscriptionName == null
+ and: 'is tagged value is false'
+ assert result.isTagged == false
+ and: 'predicates is null'
+ assert result.predicates == null
+ and: 'the topic is null'
+ assert result.topic == null
+ }
+
} \ No newline at end of file
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avcsubscription/SubscriptionEventForwarderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avcsubscription/SubscriptionEventForwarderSpec.groovy
index 2b0adf342..457eb6fa9 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avcsubscription/SubscriptionEventForwarderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/events/avcsubscription/SubscriptionEventForwarderSpec.groovy
@@ -21,6 +21,7 @@
package org.onap.cps.ncmp.api.impl.events.avcsubscription
import com.fasterxml.jackson.databind.ObjectMapper
+import com.hazelcast.map.IMap
import org.onap.cps.ncmp.api.impl.events.EventsPublisher
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
import org.onap.cps.ncmp.api.inventory.InventoryPersistence
@@ -29,20 +30,28 @@ import org.onap.cps.ncmp.event.model.SubscriptionEvent
import org.onap.cps.ncmp.utils.TestUtils
import org.onap.cps.spi.exceptions.OperationNotYetSupportedException
import org.onap.cps.utils.JsonObjectMapper
+import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
+import spock.util.concurrent.BlockingVariable
-@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper])
+@SpringBootTest(classes = [ObjectMapper, JsonObjectMapper, SubscriptionEventForwarder])
class SubscriptionEventForwarderSpec extends MessagingBaseSpec {
- def mockInventoryPersistence = Mock(InventoryPersistence)
- def mockSubscriptionEventPublisher = Mock(EventsPublisher<SubscriptionEvent>)
- def objectUnderTest = new SubscriptionEventForwarder(mockInventoryPersistence, mockSubscriptionEventPublisher)
+ @Autowired
+ SubscriptionEventForwarder objectUnderTest
+
+ @SpringBean
+ InventoryPersistence mockInventoryPersistence = Mock(InventoryPersistence)
+ @SpringBean
+ EventsPublisher<SubscriptionEvent> mockSubscriptionEventPublisher = Mock(EventsPublisher<SubscriptionEvent>)
+ @SpringBean
+ IMap<String, Set<String>> mockForwardedSubscriptionEventCache = Mock(IMap<String, Set<String>>)
@Autowired
JsonObjectMapper jsonObjectMapper
- def 'Forward valid CM create subscription'() {
+ def 'Forward valid CM create subscription and simulate timeout where #scenario'() {
given: 'an event'
def jsonData = TestUtils.getResourceFileContent('avcSubscriptionCreationEvent.json')
def testEventSent = jsonObjectMapper.convertJsonString(jsonData, SubscriptionEvent.class)
@@ -52,9 +61,17 @@ class SubscriptionEventForwarderSpec extends MessagingBaseSpec {
createYangModelCmHandleWithDmiProperty(2, 1,"shape","square"),
createYangModelCmHandleWithDmiProperty(3, 2,"shape","triangle")
]
+ and: 'the thread creation delay is reduced to 2 seconds for testing'
+ objectUnderTest.dmiResponseTimeoutInMs = 2000
+ and: 'a Blocking Variable is used for the Asynchronous call with a timeout of 5 seconds'
+ def block = new BlockingVariable<Object>(5)
when: 'the valid event is forwarded'
objectUnderTest.forwardCreateSubscriptionEvent(testEventSent)
- then: 'the event is forwarded twice with the CMHandle private properties and provides a valid listenable future'
+ then: 'An asynchronous call is made to the blocking variable'
+ block.get()
+ then: 'the event is added to the forwarded subscription event cache'
+ 1 * mockForwardedSubscriptionEventCache.put("SCO-9989752cm-subscription-001", ["DMIName1", "DMIName2"] as Set)
+ and: 'the event is forwarded twice with the CMHandle private properties and provides a valid listenable future'
1 * mockSubscriptionEventPublisher.publishEvent("ncmp-dmi-cm-avc-subscription-DMIName1", "SCO-9989752-cm-subscription-001-DMIName1",
subscriptionEvent -> {
Map targets = subscriptionEvent.getEvent().getPredicates().getTargets().get(0)
@@ -68,6 +85,15 @@ class SubscriptionEventForwarderSpec extends MessagingBaseSpec {
targets["CMHandle3"] == ["shape":"triangle"]
}
)
+ and: 'a separate thread has been created where the map is polled'
+ 1 * mockForwardedSubscriptionEventCache.containsKey("SCO-9989752cm-subscription-001") >> true
+ 1 * mockForwardedSubscriptionEventCache.get(_) >> (DMINamesInMap)
+ and: 'the subscription id is removed from the event cache map returning the asynchronous blocking variable'
+ 1 * mockForwardedSubscriptionEventCache.remove("SCO-9989752cm-subscription-001") >> {block.set(_)}
+ where:
+ scenario | DMINamesInMap
+ 'there are dmis which have not responded' | ["DMIName1", "DMIName2"] as Set
+ 'all dmis have responded ' | [] as Set
}
def 'Forward CM create subscription where target CM Handles are #scenario'() {