NCMP Java API depends on NCM-Rest-API (cyclic) through json properties on Java API
[cps.git] / cps-ncmp-service / src / test / groovy / org / onap / cps / ncmp / api / impl / NetworkCmProxyDataServiceImplRegistrationSpec.groovy
index 304c08a..a475f9c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
- *  Copyright (C) 2021 Nordix Foundation
+ *  Copyright (C) 2021-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.
@@ -22,13 +22,17 @@ package org.onap.cps.ncmp.api.impl
 
 import com.fasterxml.jackson.core.JsonProcessingException
 import com.fasterxml.jackson.databind.ObjectMapper
+import org.onap.cps.api.CpsAdminService
 import org.onap.cps.api.CpsDataService
 import org.onap.cps.api.CpsModuleService
-import org.onap.cps.ncmp.api.impl.exception.NcmpException
+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.models.CmHandle
 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
 import org.onap.cps.spi.exceptions.DataNodeNotFoundException
 import org.onap.cps.spi.exceptions.DataValidationException
+import org.onap.cps.utils.JsonObjectMapper
 import spock.lang.Shared
 import spock.lang.Specification
 
@@ -44,50 +48,58 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
 
     def mockCpsDataService = Mock(CpsDataService)
     def mockCpsModuleService = Mock(CpsModuleService)
-    def spyObjectMapper = Spy(ObjectMapper)
+    def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper()))
+    def mockCpsAdminService = Mock(CpsAdminService)
+    def mockDmiModelOperations = Mock(DmiModelOperations)
+    def mockDmiDataOperations = Mock(DmiDataOperations)
+    def mockNetworkCmProxyDataServicePropertyHandler = Mock(NetworkCmProxyDataServicePropertyHandler)
 
     def noTimestamp = null
 
     def 'Register or re-register a DMI Plugin for the given cm-handle(s) with #scenario process.'() {
         given: 'a registration'
             def objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
-            def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server')
+            def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
             persistenceCmHandle.cmHandleID = '123'
-            persistenceCmHandle.cmHandleProperties = [name1: 'value1', name2: 'value2']
+            persistenceCmHandle.dmiProperties = [dmiProp1: 'dmiValue1', dmiProp2: 'dmiValue2']
+            persistenceCmHandle.publicProperties = [publicProp1: 'publicValue1', publicProp2: 'publicValue2']
             dmiPluginRegistration.createdCmHandles = createdCmHandles
             dmiPluginRegistration.updatedCmHandles = updatedCmHandles
             dmiPluginRegistration.removedCmHandles = removedCmHandles
-            def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[{"name":"name1","value":"value1"},{"name":"name2","value":"value2"}]}]}'
+            def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,' +
+                '"additional-properties":[{"name":"dmiProp1","value":"dmiValue1"},{"name":"dmiProp2","value":"dmiValue2"}],' +
+                '"public-properties":[{"name":"publicProp1","value":"publicValue1"},{"name":"publicProp2","value":"publicValue2"}]' +
+                '}]}'
         when: 'registration is updated and modules are synced'
             objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
         then: 'save list elements is invoked with the expected parameters'
             expectedCallsToSaveNode * mockCpsDataService.saveListElements('NCMP-Admin', 'ncmp-dmi-registry',
-                    '/dmi-registry', expectedJsonData, noTimestamp)
-        and: 'update node and child data nodes is invoked with correct parameters'
-            expectedCallsToUpdateNode * mockCpsDataService.updateNodeLeavesAndExistingDescendantLeaves('NCMP-Admin',
-                    'ncmp-dmi-registry', '/dmi-registry', expectedJsonData, noTimestamp)
+                '/dmi-registry', expectedJsonData, noTimestamp)
+        and: 'update data node leaves is called with correct parameters'
+            expectedCallsToUpdateCmHandleProperty * mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(updatedCmHandles)
         and: 'delete schema set is invoked with the correct parameters'
             expectedCallsToDeleteSchemaSetAndListElement * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'cmHandle001', CASCADE_DELETE_ALLOWED)
         and: 'delete list or list element is invoked with the correct parameters'
             expectedCallsToDeleteSchemaSetAndListElement * mockCpsDataService.deleteListOrListElement('NCMP-Admin',
-                    'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp)
+                'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp)
         where:
-            scenario                    | createdCmHandles      | updatedCmHandles      | removedCmHandles || expectedCallsToSaveNode | expectedCallsToUpdateNode | expectedCallsToDeleteSchemaSetAndListElement
-            'create'                    | [persistenceCmHandle] | []                    | []               || 1                       | 0                         | 0
-            'update'                    | []                    | [persistenceCmHandle] | []               || 0                       | 1                         | 0
-            'delete'                    | []                    | []                    | cmHandlesArray   || 0                       | 0                         | 1
-            'create, update and delete' | [persistenceCmHandle] | [persistenceCmHandle] | cmHandlesArray   || 1                       | 1                         | 1
-            'no valid data'             | null                  | null                  | null             || 0                       | 0                         | 0
+            scenario                    | createdCmHandles      | updatedCmHandles      | removedCmHandles || expectedCallsToSaveNode | expectedCallsToDeleteSchemaSetAndListElement | expectedCallsToUpdateCmHandleProperty
+            'create'                    | [persistenceCmHandle] | []                    | []               || 1                       | 0                                            | 0
+            'update'                    | []                    | [persistenceCmHandle] | []               || 0                       | 0                                            | 1
+            'delete'                    | []                    | []                    | cmHandlesArray   || 0                       | 1                                            | 0
+            'create, update and delete' | [persistenceCmHandle] | [persistenceCmHandle] | cmHandlesArray   || 1                       | 1                                            | 1
+            'no valid data'             | []                    | []                    | []               || 0                       | 0                                            | 0
     }
 
-    def 'Register a DMI Plugin for the given cm-handle(s) without additional properties.'() {
+    def 'Register a DMI Plugin for the given cm-handle(s) without DMI properties.'() {
         given: 'a registration without cm-handle properties'
             NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
             def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server')
             persistenceCmHandle.cmHandleID = '123'
-            persistenceCmHandle.cmHandleProperties = null
+            persistenceCmHandle.dmiProperties = Collections.emptyMap()
+            persistenceCmHandle.publicProperties = Collections.emptyMap()
             dmiPluginRegistration.createdCmHandles = [persistenceCmHandle]
-            def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[]}]}'
+            def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[],"public-properties":[]}]}'
         when: 'registration is updated'
             objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
         then: 'save list elements is invoked with the expected parameters'
@@ -95,22 +107,17 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
                     '/dmi-registry', expectedJsonData, noTimestamp)
     }
 
-    def 'Register a DMI Plugin for a given cm-handle(s) with JSON processing errors during #scenario process.'() {
+    def 'Register a DMI Plugin for a given cm-handle(s) with JSON processing errors during process.'() {
         given: 'a registration without cm-handle properties '
             NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
             def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'some-plugin')
-            dmiPluginRegistration.createdCmHandles = createdCmHandles
-            dmiPluginRegistration.updatedCmHandles = updatedCmHandles
+            dmiPluginRegistration.createdCmHandles = [persistenceCmHandle]
         and: 'an json processing exception occurs'
-            spyObjectMapper.writeValueAsString(_) >> { throw (new JsonProcessingException('')) }
+            spiedJsonObjectMapper.asJsonString(_) >> { throw (new JsonProcessingException('')) }
         when: 'registration is updated and modules are synced'
             objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
         then: 'a data validation exception is thrown'
             thrown(DataValidationException)
-        where:
-            scenario | createdCmHandles      | updatedCmHandles
-            'create' | [persistenceCmHandle] | []
-            'update' | []                    | [persistenceCmHandle]
     }
 
     def 'Register a DMI Plugin for the given cm-handle(s) with no data found during delete process.'() {
@@ -156,7 +163,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
             'data & model using same service' | ''         | 'service1'     | 'service1'
     }
 
-    def 'Invalid dmi plugin registration with #scenario'() {
+    def 'Invalid DMI plugin registration with #scenario'() {
         given: 'a registration '
             def objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
             def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:dmiPlugin, dmiModelPlugin:dmiModelPlugin,
@@ -164,8 +171,8 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
             dmiPluginRegistration.createdCmHandles = [persistenceCmHandle]
         when: 'registration is called with incorrect DMI plugin information'
             objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
-        then: 'an NcmpException is thrown with correct message details'
-            def exceptionThrown = thrown(NcmpException)
+        then: 'a DMI Request Exception is thrown with correct message details'
+            def exceptionThrown = thrown(DmiRequestException.class)
             assert exceptionThrown.getMessage().contains(expectedMessageDetails)
         and: 'registration is not called'
             0 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)
@@ -181,9 +188,25 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
             'only data DMI plugin'          | ''         | ''             | 'service1'    || 'Cannot register just a Data or Model plugin service name'
     }
 
+    def 'Exception thrown on CM-Handle registration update request'() {
+        given: 'a CM-handle registration'
+            def objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
+        and: 'dmi plugin registration input update request'
+            def dmiPluginReg = new DmiPluginRegistration();
+            dmiPluginReg.dmiPlugin = 'onap.dmap.plugin';
+            dmiPluginReg.updatedCmHandles = [new CmHandle(cmHandleID: 'unknownHandle')]
+        and: 'update data node leaves is unable to find data node'
+            mockNetworkCmProxyDataServicePropertyHandler.updateCmHandleProperties(*_) >> { throw new DataNodeNotFoundException('NCMP-Admin', 'ncmp-dmi-registry') }
+        when: 'update dmi registration is called'
+            objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginReg)
+        then: 'data validation exception is thrown'
+            def exceptionThrown = thrown(DataValidationException.class)
+            assert exceptionThrown.getDetails().contains('DataNode not found')
+    }
+
     def getObjectUnderTestWithModelSyncDisabled() {
-        def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(null, null, mockCpsModuleService,
-                mockCpsDataService, null, null, spyObjectMapper))
+        def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(mockCpsDataService, spiedJsonObjectMapper, mockDmiDataOperations, mockDmiModelOperations,
+            mockCpsModuleService, mockCpsAdminService, mockNetworkCmProxyDataServicePropertyHandler))
         objectUnderTest.syncModulesAndCreateAnchor(*_) >> null
         return objectUnderTest
     }