2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.ncmp.api.impl
23 import com.fasterxml.jackson.core.JsonProcessingException
24 import com.fasterxml.jackson.databind.ObjectMapper
25 import org.onap.cps.api.CpsDataService
26 import org.onap.cps.ncmp.api.impl.exception.NcmpException
27 import org.onap.cps.ncmp.api.models.CmHandle
28 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
29 import org.onap.cps.spi.exceptions.DataNodeNotFoundException
30 import org.onap.cps.spi.exceptions.DataValidationException
31 import spock.lang.Shared
32 import spock.lang.Specification
34 class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
37 def persistenceCmHandle = new CmHandle()
40 def cmHandlesArray = ['cmHandle001']
42 def mockCpsDataService = Mock(CpsDataService)
43 def spyObjectMapper = Spy(ObjectMapper)
45 def noTimestamp = null
47 def 'Register or re-register a DMI Plugin for the given cm-handle(s) with #scenario process.'() {
48 given: 'a registration'
49 def objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
50 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server')
51 persistenceCmHandle.cmHandleID = '123'
52 persistenceCmHandle.cmHandleProperties = [name1: 'value1', name2: 'value2']
53 dmiPluginRegistration.createdCmHandles = createdCmHandles
54 dmiPluginRegistration.updatedCmHandles = updatedCmHandles
55 dmiPluginRegistration.removedCmHandles = removedCmHandles
56 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"}]}]}'
57 when: 'registration is updated and modules are synced'
58 objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
59 then: 'save list elements is invoked with the expected parameters'
60 expectedCallsToSaveNode * mockCpsDataService.saveListElements('NCMP-Admin', 'ncmp-dmi-registry',
61 '/dmi-registry', expectedJsonData, noTimestamp)
62 and: 'update node and child data nodes is invoked with correct parameters'
63 expectedCallsToUpdateNode * mockCpsDataService.updateNodeLeavesAndExistingDescendantLeaves('NCMP-Admin',
64 'ncmp-dmi-registry', '/dmi-registry', expectedJsonData, noTimestamp)
65 and : 'delete list or list element is invoked with the correct parameters'
66 expectedCallsToDeleteListElement * mockCpsDataService.deleteListOrListElement('NCMP-Admin',
67 'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp)
69 scenario | createdCmHandles | updatedCmHandles | removedCmHandles || expectedCallsToSaveNode | expectedCallsToUpdateNode | expectedCallsToDeleteListElement
70 'create' | [persistenceCmHandle] | [] | [] || 1 | 0 | 0
71 'update' | [] | [persistenceCmHandle] | [] || 0 | 1 | 0
72 'delete' | [] | [] | cmHandlesArray || 0 | 0 | 1
73 'create, update and delete' | [persistenceCmHandle] | [persistenceCmHandle] | cmHandlesArray || 1 | 1 | 1
74 'no valid data' | null | null | null || 0 | 0 | 0
77 def 'Register a DMI Plugin for the given cm-handle(s) without additional properties.'() {
78 given: 'a registration without cm-handle properties'
79 NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
80 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'my-server')
81 persistenceCmHandle.cmHandleID = '123'
82 persistenceCmHandle.cmHandleProperties = null
83 dmiPluginRegistration.createdCmHandles = [persistenceCmHandle]
84 def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","dmi-data-service-name":null,"dmi-model-service-name":null,"additional-properties":[]}]}'
85 when: 'registration is updated'
86 objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
87 then: 'save list elements is invoked with the expected parameters'
88 1 * mockCpsDataService.saveListElements('NCMP-Admin', 'ncmp-dmi-registry',
89 '/dmi-registry', expectedJsonData, noTimestamp)
92 def 'Register a DMI Plugin for a given cm-handle(s) with JSON processing errors during #scenario process.'() {
93 given: 'a registration without cm-handle properties '
94 NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
95 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'some-plugin')
96 dmiPluginRegistration.createdCmHandles = createdCmHandles
97 dmiPluginRegistration.updatedCmHandles = updatedCmHandles
98 and: 'an json processing exception occurs'
99 spyObjectMapper.writeValueAsString(_) >> { throw (new JsonProcessingException('')) }
100 when: 'registration is updated and modules are synced'
101 objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
102 then: 'a data validation exception is thrown'
103 thrown(DataValidationException)
105 scenario | createdCmHandles | updatedCmHandles
106 'create' | [persistenceCmHandle] | []
107 'update' | [] | [persistenceCmHandle]
110 def 'Register a DMI Plugin for the given cm-handle(s) with no data found during delete process.'() {
111 given: 'a registration without cm-handle properties '
112 NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
113 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:'some-plugin')
114 dmiPluginRegistration.removedCmHandles = ['some cm handle']
115 and: 'an json processing exception occurs during delete process'
116 mockCpsDataService.deleteListOrListElement(*_) >> { throw (new DataNodeNotFoundException('','')) }
117 when: 'registration is updated and modules are synced'
118 objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
119 then: 'no exception is thrown'
123 def 'Dmi plugin registration with #scenario'() {
124 given: 'a registration '
125 def objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
126 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:dmiPlugin, dmiModelPlugin:dmiModelPlugin,
127 dmiDataPlugin:dmiDataPlugin)
128 dmiPluginRegistration.createdCmHandles = [persistenceCmHandle]
129 when: 'update registration and sync module is called with correct DMI plugin information'
130 objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
131 then: 'create cm handles registration and sync modules is called with the correct plugin information'
132 1 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)
134 scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin
135 'combined DMI plugin' | 'service1' | '' | ''
136 'data & model DMI plugins' | '' | 'service1' | 'service2'
137 'data & model using same service' | '' | 'service1' | 'service1'
140 def 'Invalid dmi plugin registration with #scenario'() {
141 given: 'a registration '
142 def objectUnderTest = getObjectUnderTestWithModelSyncDisabled()
143 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin:dmiPlugin, dmiModelPlugin:dmiModelPlugin,
144 dmiDataPlugin:dmiDataPlugin)
145 dmiPluginRegistration.createdCmHandles = [persistenceCmHandle]
146 when: 'registration is called with incorrect DMI plugin information'
147 objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
148 then: 'an NcmpException is thrown with correct message details'
149 def exceptionThrown = thrown(NcmpException)
150 assert exceptionThrown.getMessage().contains(expectedMessageDetails)
151 and: 'registration is not called'
152 0 * objectUnderTest.parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(dmiPluginRegistration)
154 scenario | dmiPlugin | dmiModelPlugin | dmiDataPlugin || expectedMessageDetails
155 'no DMI plugin' | '' | '' | '' || 'No DMI plugin service names'
156 'all DMI plugins' | 'service1' | 'service2' | 'service3' || 'Invalid combination of plugin service names'
157 'no model DMI plugin' | 'service1' | '' | 'service2' || 'Invalid combination of plugin service names'
158 'no data DMI plugin' | 'service1' | 'service2' | '' || 'Invalid combination of plugin service names'
161 def getObjectUnderTestWithModelSyncDisabled() {
162 def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(null, null, null,
163 mockCpsDataService, null, null, spyObjectMapper))
164 objectUnderTest.syncModulesAndCreateAnchor(*_) >> null
165 return objectUnderTest