Remove CmHandle in DMI-Registry
[cps.git] / cps-ncmp-service / src / test / groovy / org / onap / cps / ncmp / api / impl / NetworkCmProxyDataServiceImplSpec.groovy
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 Nordix Foundation
4  *  Modifications Copyright (C) 2021 Pantheon.tech
5  *  ================================================================================
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *        http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  *
18  *  SPDX-License-Identifier: Apache-2.0
19  *  ============LICENSE_END=========================================================
20  */
21
22 package org.onap.cps.ncmp.api.impl
23
24 import com.fasterxml.jackson.core.JsonProcessingException
25 import com.fasterxml.jackson.databind.ObjectMapper
26 import org.onap.cps.api.CpsDataService
27 import org.onap.cps.api.CpsQueryService
28 import org.onap.cps.ncmp.api.impl.exception.NcmpException
29 import org.onap.cps.ncmp.api.impl.operation.DmiOperations
30 import org.onap.cps.ncmp.api.models.CmHandle
31 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
32 import org.onap.cps.spi.FetchDescendantsOption
33 import org.onap.cps.spi.model.DataNode
34 import org.springframework.http.HttpStatus
35 import org.springframework.http.ResponseEntity
36 import spock.lang.Shared
37 import spock.lang.Specification
38
39 class NetworkCmProxyDataServiceImplSpec extends Specification {
40
41     @Shared
42     def persistenceCmHandle = new CmHandle()
43     @Shared
44     def cmHandlesArray = ['cmHandle001']
45
46     def mockCpsDataService = Mock(CpsDataService)
47     def mockCpsQueryService = Mock(CpsQueryService)
48     def mockDmiOperations = Mock(DmiOperations)
49     def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockDmiOperations, mockCpsDataService, mockCpsQueryService, new ObjectMapper())
50
51     def cmHandle = 'some handle'
52
53     def expectedDataspaceName = 'NFP-Operational'
54     def 'Query data nodes by cps path with #fetchDescendantsOption.'() {
55         given: 'a cm Handle and a cps path'
56             def cpsPath = '/cps-path'
57         when: 'queryDataNodes is invoked'
58             objectUnderTest.queryDataNodes(cmHandle, cpsPath, fetchDescendantsOption)
59         then: 'the persistence service is called once with the correct parameters'
60             1 * mockCpsQueryService.queryDataNodes(expectedDataspaceName, cmHandle, cpsPath, fetchDescendantsOption)
61         where: 'all fetch descendants options are supported'
62             fetchDescendantsOption << FetchDescendantsOption.values()
63     }
64     def 'Create full data node: #scenario.'() {
65         given: 'a cm handle and root xpath'
66             def jsonData = 'some json'
67         when: 'createDataNode is invoked'
68             objectUnderTest.createDataNode(cmHandle, xpath, jsonData)
69         then: 'the CPS service method is invoked once with the expected parameters'
70             1 * mockCpsDataService.saveData(expectedDataspaceName, cmHandle, jsonData)
71         where: 'following parameters were used'
72             scenario           | xpath
73             'no xpath'         | ''
74             'root level xpath' | '/'
75     }
76     def 'Create child data node.'() {
77         given: 'a cm handle and parent node xpath'
78             def jsonData = 'some json'
79             def xpath = '/test-node'
80         when: 'createDataNode is invoked'
81             objectUnderTest.createDataNode(cmHandle, xpath, jsonData)
82         then: 'the CPS service method is invoked once with the expected parameters'
83             1 * mockCpsDataService.saveData(expectedDataspaceName, cmHandle, xpath, jsonData)
84     }
85     def 'Add list-node elements.'() {
86         given: 'a cm handle and parent node xpath'
87             def jsonData = 'some json'
88             def xpath = '/test-node'
89         when: 'addListNodeElements is invoked'
90             objectUnderTest.addListNodeElements(cmHandle, xpath, jsonData)
91         then: 'the CPS service method is invoked once with the expected parameters'
92             1 * mockCpsDataService.saveListNodeData(expectedDataspaceName, cmHandle, xpath, jsonData)
93     }
94     def 'Update data node leaves.'() {
95         given: 'a cm Handle and a cps path'
96             def xpath = '/xpath'
97             def jsonData = 'some json'
98         when: 'updateNodeLeaves is invoked'
99             objectUnderTest.updateNodeLeaves(cmHandle, xpath, jsonData)
100         then: 'the persistence service is called once with the correct parameters'
101             1 * mockCpsDataService.updateNodeLeaves(expectedDataspaceName, cmHandle, xpath, jsonData)
102     }
103     def 'Replace data node tree.'() {
104         given: 'a cm Handle and a cps path'
105             def xpath = '/xpath'
106             def jsonData = 'some json'
107         when: 'replaceNodeTree is invoked'
108             objectUnderTest.replaceNodeTree(cmHandle, xpath, jsonData)
109         then: 'the persistence service is called once with the correct parameters'
110             1 * mockCpsDataService.replaceNodeTree(expectedDataspaceName, cmHandle, xpath, jsonData)
111     }
112
113     def 'Register or re-register a DMI Plugin with #scenario cm handles.'() {
114         given: 'a registration '
115             def dmiPluginRegistration = new DmiPluginRegistration()
116             dmiPluginRegistration.dmiPlugin = 'my-server'
117             persistenceCmHandle.cmHandleID = '123'
118             persistenceCmHandle.cmHandleProperties = [name1: 'value1', name2: 'value2']
119             dmiPluginRegistration.createdCmHandles = createdCmHandles
120             dmiPluginRegistration.updatedCmHandles = updatedCmHandles
121             dmiPluginRegistration.removedCmHandles = removedCmHandles
122             def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","additional-properties":[{"name":"name1","value":"value1"},{"name":"name2","value":"value2"}]}]}'
123         when: 'registration is updated'
124             objectUnderTest.updateDmiPluginRegistration(dmiPluginRegistration)
125         then: 'the CPS save list node data is invoked with the expected parameters'
126             expectedCallsToSaveNode * mockCpsDataService.saveListNodeData('NCMP-Admin', 'ncmp-dmi-registry', '/dmi-registry', expectedJsonData)
127         and: 'update Node and Child Data Nodes is invoked with correct parameters'
128             expectedCallsToUpdateNode * mockCpsDataService.updateNodeLeavesAndExistingDescendantLeaves('NCMP-Admin',  'ncmp-dmi-registry', '/dmi-registry', expectedJsonData)
129         and : 'delete list data node is invoked with the correct parameters'
130             expectedCallsToDeleteListDataNode * mockCpsDataService.deleteListNodeData('NCMP-Admin', 'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']")
131         where:
132             scenario                        | createdCmHandles       | updatedCmHandles       | removedCmHandles || expectedCallsToSaveNode   | expectedCallsToUpdateNode | expectedCallsToDeleteListDataNode
133             'create'                        | [persistenceCmHandle ] | []                     | []               || 1                         | 0                         | 0
134             'update'                        | []                     | [persistenceCmHandle ] | []               || 0                         | 1                         | 0
135             'delete'                        | []                     | []                     | cmHandlesArray   || 0                         | 0                         | 1
136             'create, update and delete'     | [persistenceCmHandle ] | [persistenceCmHandle ] | cmHandlesArray   || 1                         | 1                         | 1
137
138     }
139     def 'Get resource data for pass-through operational from dmi.'() {
140         given: 'xpath'
141             def xpath = "/dmi-registry/cm-handles[@id='testCmHandle']"
142         and: 'data node'
143             def dataNode = new DataNode()
144             dataNode.leaves = ['dmi-service-name':'testDmiService']
145             def childDataNode = new DataNode()
146             childDataNode.leaves = ['name':'testName','value':'testValue']
147             dataNode.childDataNodes = [childDataNode]
148         when: 'get resource data is called'
149             def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
150             'testResourceId',
151             'testAcceptParam',
152             'testFieldQuery',
153             5)
154         then: 'cps data service is being called once to get data node'
155             1 * mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
156                     xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
157         and: 'dmi operation is being called to get resource data'
158             1 * mockDmiOperations.getResouceDataOperationalFromDmi('testDmiService',
159                     'testCmHandle',
160                     'testResourceId',
161                     'testFieldQuery',
162                     5,
163                     'testAcceptParam',
164             '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}') >> new ResponseEntity<>('result-json', HttpStatus.OK)
165         and: 'dmi returns ok response'
166             response == 'result-json'
167     }
168     def 'Get resource data for pass-through operational from dmi threw parsing exception.'() {
169         given: 'xpath'
170             def xpath = "/dmi-registry/cm-handles[@id='testCmHandle']"
171         and: 'data node'
172             def dataNode = new DataNode()
173             dataNode.leaves = ['dmi-service-name':'testDmiService']
174             def childDataNode = new DataNode()
175             childDataNode.leaves = ['name':'testName','value':'testValue']
176             dataNode.childDataNodes = [childDataNode]
177             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
178                     xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
179         and: 'objectMapper not able to parse object'
180             def mockObjectMapper = Mock(ObjectMapper)
181             objectUnderTest.objectMapper = mockObjectMapper
182             mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException("testException") }
183         when: 'get resource data is called'
184             def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
185                     'testResourceId',
186                     'testAcceptParam',
187                     'testFieldQuery',
188                     5)
189         then: 'exception is thrown'
190             thrown(NcmpException.class)
191     }
192     def 'Get resource data for pass-through operational from dmi return NOK response.'() {
193         given: 'xpath'
194             def xpath = "/dmi-registry/cm-handles[@id='testCmHandle']"
195         and: 'data node'
196             def dataNode = new DataNode()
197             dataNode.leaves = ['dmi-service-name':'testDmiService']
198             def childDataNode = new DataNode()
199             childDataNode.leaves = ['name':'testName','value':'testValue']
200             dataNode.childDataNodes = [childDataNode]
201             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
202                     xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
203         and: 'dmi returns NOK response'
204             mockDmiOperations.getResouceDataOperationalFromDmi('testDmiService',
205                     'testCmHandle',
206                     'testResourceId',
207                     'testFieldQuery',
208                     5,
209                     'testAcceptParam',
210                     '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}')
211                     >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
212         when: 'get resource data is called'
213             def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle',
214                     'testResourceId',
215                     'testAcceptParam',
216                     'testFieldQuery',
217                     5)
218         then: 'exception is thrown'
219             thrown(NcmpException.class)
220     }
221     def 'Get resource data for pass-through running from dmi.'() {
222         given: 'xpath'
223             def xpath = "/dmi-registry/cm-handles[@id='testCmHandle']"
224         and: 'data node representing cmhandle and its properties'
225             def dataNode = new DataNode()
226             dataNode.leaves = ['dmi-service-name':'testDmiService']
227             def childDataNode = new DataNode()
228             childDataNode.leaves = ['name':'testName','value':'testValue']
229             dataNode.childDataNodes = [childDataNode]
230         and: 'cpsDataService returns valid dataNode'
231             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
232                     xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
233         and: 'dmi returns valid response and data'
234             mockDmiOperations.getResouceDataPassThroughRunningFromDmi('testDmiService',
235                     'testCmHandle',
236                     'testResourceId',
237                     'testFieldQuery',
238                     5,
239                     'testAcceptParam',
240                     '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}') >> new ResponseEntity<>('{result-json}', HttpStatus.OK)
241         when: 'get resource data is called'
242             def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
243                     'testResourceId',
244                     'testAcceptParam',
245                     'testFieldQuery',
246                     5)
247         then: 'get resource data returns expected response'
248             response == '{result-json}'
249     }
250     def 'Get resource data for pass-through running from dmi threw parsing exception.'() {
251         given: 'xpath'
252             def xpath = "/dmi-registry/cm-handles[@id='testCmHandle']"
253         and: 'data node representing cmhandle and its properties'
254             def dataNode = new DataNode()
255             dataNode.leaves = ['dmi-service-name':'testDmiService']
256             def childDataNode = new DataNode()
257             childDataNode.leaves = ['name':'testName','value':'testValue']
258             dataNode.childDataNodes = [childDataNode]
259         and: 'cpsDataService returns valid dataNode'
260             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
261                     xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
262         and: 'objectMapper not able to parse object'
263             def mockObjectMapper = Mock(ObjectMapper)
264             objectUnderTest.objectMapper = mockObjectMapper
265             mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException("testException") }
266         when: 'get resource data is called'
267             def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
268                     'testResourceId',
269                     'testAcceptParam',
270                     'testFieldQuery',
271                     5)
272         then: 'exception is thrown'
273             thrown(NcmpException.class)
274     }
275     def 'Get resource data for pass-through running from dmi return NOK response.'() {
276         given: 'xpath'
277             def xpath = "/dmi-registry/cm-handles[@id='testCmHandle']"
278         and: 'data node representing cmhandle and its properties'
279             def dataNode = new DataNode()
280             dataNode.leaves = ['dmi-service-name':'testDmiService']
281             def childDataNode = new DataNode()
282             childDataNode.leaves = ['name':'testName','value':'testValue']
283             dataNode.childDataNodes = [childDataNode]
284         and: 'cpsDataService returns valid dataNode'
285             mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
286                     xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> dataNode
287         and: 'dmi returns NOK response'
288             mockDmiOperations.getResouceDataPassThroughRunningFromDmi('testDmiService',
289                     'testCmHandle',
290                     'testResourceId',
291                     'testFieldQuery',
292                     5,
293                     'testAcceptParam',
294                     '{"operation":"read","cmHandleProperties":{"testName":"testValue"}}')
295                     >> new ResponseEntity<>('NOK-json', HttpStatus.NOT_FOUND)
296         when: 'get resource data is called'
297             def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
298                     'testResourceId',
299                     'testAcceptParam',
300                     'testFieldQuery',
301                     5)
302         then: 'exception is thrown'
303             thrown(NcmpException.class)
304     }
305 }