Improve coverage with unit tests 98/142398/1
authoremaclee <lee.anjella.macabuhay@est.tech>
Mon, 10 Nov 2025 15:06:25 +0000 (15:06 +0000)
committeremaclee <lee.anjella.macabuhay@est.tech>
Mon, 10 Nov 2025 15:06:25 +0000 (15:06 +0000)
- removed unused records in data job subscriptions
- add unit test to cover deleting a non existing subscription
- add unit test in YangDataCoverter for xpath ending with
  'state'

Issue-ID: CPS-3036
Change-Id: Ia3439f12806971573501ebe17debb2c10b5bf6db
Signed-off-by: emaclee <lee.anjella.macabuhay@est.tech>
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/subscription/models/DmiCmSubscriptionKey.java [deleted file]
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/subscription/models/DmiCmSubscriptionTuple.java [deleted file]
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/datajobs/subscription/utils/CmSubscriptionPersistenceServiceSpec.groovy
cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/YangDataConverterSpec.groovy

diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/subscription/models/DmiCmSubscriptionKey.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/subscription/models/DmiCmSubscriptionKey.java
deleted file mode 100644 (file)
index e67706a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2024 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.impl.datajobs.subscription.models;
-
-/**
- * Key used to find the records to be sent to the DMI plugin.
- *
- * @param datastoreName datastore name
- * @param cmHandleId    cmhandle id
- * @param xpath         xpath
- */
-public record DmiCmSubscriptionKey(String datastoreName, String cmHandleId, String xpath) {
-}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/subscription/models/DmiCmSubscriptionTuple.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/datajobs/subscription/models/DmiCmSubscriptionTuple.java
deleted file mode 100644 (file)
index e76924c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2024 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.impl.datajobs.subscription.models;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * Tuple to be used during for to delete use case.
- *
- * @param lastRemainingSubscriptionsPerDmi subscriptions that are used by only one subscriber grouped per dmi
- * @param overlappingSubscriptionsPerDmi   subscriptions that are shared by multiple subscribers grouped per dmi
- */
-public record DmiCmSubscriptionTuple(Map<String, Collection<DmiCmSubscriptionKey>> lastRemainingSubscriptionsPerDmi,
-                                     Map<String, Collection<DmiCmSubscriptionKey>> overlappingSubscriptionsPerDmi) {
-}
index a3e994d..adc8803 100644 (file)
@@ -29,6 +29,11 @@ import static CmDataJobSubscriptionPersistenceService.PARENT_NODE_XPATH
 import static org.onap.cps.ncmp.impl.datajobs.subscription.models.CmSubscriptionStatus.ACCEPTED
 import static org.onap.cps.api.parameters.FetchDescendantsOption.OMIT_DESCENDANTS
 
+import ch.qos.logback.classic.Level
+import ch.qos.logback.classic.Logger
+import ch.qos.logback.classic.spi.ILoggingEvent
+import ch.qos.logback.core.read.ListAppender
+import org.slf4j.LoggerFactory
 import com.fasterxml.jackson.databind.ObjectMapper
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsQueryService
@@ -42,9 +47,20 @@ class CmSubscriptionPersistenceServiceSpec extends Specification {
     def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
     def mockCpsQueryService = Mock(CpsQueryService)
     def mockCpsDataService = Mock(CpsDataService)
+    def logAppender = Spy(ListAppender<ILoggingEvent>)
 
     def objectUnderTest = new CmDataJobSubscriptionPersistenceService(jsonObjectMapper, mockCpsQueryService, mockCpsDataService)
 
+    void setup() {
+        def logger = LoggerFactory.getLogger(CmDataJobSubscriptionPersistenceService)
+        logger.addAppender(logAppender)
+        logAppender.start()
+    }
+
+    void cleanup() {
+        ((Logger) LoggerFactory.getLogger(CmDataJobSubscriptionPersistenceService.class)).detachAndStopAllAppenders()
+    }
+
     def 'Check cm data job subscription details has at least one subscriber #scenario'() {
         given: 'a valid cm data job subscription query'
             def cpsPathQuery = CPS_PATH_TEMPLATE_FOR_SUBSCRIPTIONS_WITH_DATA_NODE_SELECTOR.formatted('/myDataNodeSelector')
@@ -169,6 +185,22 @@ class CmSubscriptionPersistenceServiceSpec extends Specification {
             }, _, ContentType.JSON)
     }
 
+    def 'Delete subscription that does not exist'() {
+        given: 'the query service returns data node for given data node selector'
+            def query = CPS_PATH_TEMPLATE_FOR_SUBSCRIPTIONS_WITH_DATA_NODE_SELECTOR.formatted('/myDataNodeSelector')
+            def dataNode = new DataNode(leaves: ['dataJobId': ['some-id'], 'status': 'ACCEPTED'])
+            mockCpsQueryService.queryDataNodes('NCMP-Admin', 'cm-data-job-subscriptions', query, OMIT_DESCENDANTS) >> [dataNode]
+        when: 'deleting a subscription on a data node selector'
+            objectUnderTest.delete('non-existing-id', '/myDataNodeSelector')
+        then: 'no exception thrown'
+            noExceptionThrown()
+        and: 'an event is logged with level INFO'
+            def loggingEvent = logAppender.list[0]
+            assert loggingEvent.level == Level.WARN
+        and: 'the log indicates subscription id does not exist for data node selector'
+            assert loggingEvent.formattedMessage == 'SubscriptionId=non-existing-id not found under dataNodeSelector=/myDataNodeSelector'
+    }
+
     def 'Update status of a subscription.'() {
         given: 'a data node selector and status'
             def myDataNodeSelector = "/myDataNodeSelector"
index df669e6..1729d75 100644 (file)
 
 package org.onap.cps.ncmp.impl.utils
 
+import static org.onap.cps.ncmp.api.inventory.models.CmHandleState.ADVISED
+
 import org.onap.cps.api.model.DataNode
 import spock.lang.Specification
 
 class YangDataConverterSpec extends Specification{
 
-    def 'Convert a cm handle data node with additional and public properties.'() {
-        given: 'a datanode with some additional and public properties'
+    def 'Convert a cm handle data node with additional properties, public properties and state.'() {
+        given: 'a datanode with some additional properties, public properties and state'
             def dataNodeAdditionalProperties = new DataNode(xpath:'/additional-properties[@name="dmiProp1"]',
                     leaves: ['name': 'dmiProp1', 'value': 'dmiValue1'])
             def dataNodePublicProperties = new DataNode(xpath:'/public-properties[@name="pubProp1"]',
                     leaves: ['name': 'pubProp1', 'value': 'pubValue1'])
-            def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id', 'alternate-id': 'alt-id', 'module-set-tag': 'my-tag', 'dmi-service-name': 'my-dmi', 'data-producer-identifier': 'my-dpi'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties])
+            def dataNodeState = new DataNode(xpath:'/parent/state', leaves: ['cm-handle-state': 'ADVISED', 'last-update-time': 'now'])
+            def dataNodeCmHandle = new DataNode(leaves:['id':'sample-id', 'alternate-id': 'alt-id', 'module-set-tag': 'my-tag', 'dmi-service-name': 'my-dmi', 'data-producer-identifier': 'my-dpi'], childDataNodes:[dataNodeAdditionalProperties, dataNodePublicProperties, dataNodeState])
         when: 'the dataNode is converted'
             def yangModelCmHandle = YangDataConverter.toYangModelCmHandle(dataNodeCmHandle)
         then: 'the converted object has the fields'
@@ -46,6 +49,9 @@ class YangDataConverterSpec extends Specification{
         and: 'the public properties are included'
             assert yangModelCmHandle.publicProperties[0].name == 'pubProp1'
             assert yangModelCmHandle.publicProperties[0].value == 'pubValue1'
+        and: 'the composite state is set'
+            assert yangModelCmHandle.compositeState.lastUpdateTime == 'now'
+            assert yangModelCmHandle.compositeState.cmHandleState == ADVISED
     }
 
     def 'Convert multiple cm handle data nodes'(){