2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Pantheon.tech
4 * Modification Copyright (C) 2021 highstreet technologies GmbH
5 * Modification Copyright (C) 2021 Nordix Foundation
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.cps.ncmp.rest.controller
24 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
25 import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS
26 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
27 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
28 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
29 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
31 import com.fasterxml.jackson.databind.ObjectMapper
32 import com.google.gson.Gson
33 import org.onap.cps.TestUtils
34 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
35 import org.onap.cps.spi.model.DataNodeBuilder
36 import org.spockframework.spring.SpringBean
37 import org.springframework.beans.factory.annotation.Autowired
38 import org.springframework.beans.factory.annotation.Value
39 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
40 import org.springframework.http.HttpStatus
41 import org.springframework.http.MediaType
42 import org.springframework.test.web.servlet.MockMvc
43 import spock.lang.Specification
46 class NetworkCmProxyControllerSpec extends Specification {
52 NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
55 ObjectMapper objectMapper = new ObjectMapper()
57 @Value('${rest.api.ncmp-base-path}')
60 def deprecatedDataNodeBaseEndPoint
65 deprecatedDataNodeBaseEndPoint = "$basePath/v1"
66 ncmpDmiEndpoint = "$basePath/ncmp-dmi/v1"
69 def cmHandle = 'some handle'
70 def xpath = 'some xpath'
72 def 'Query data node by cps path for the given cm handle with #scenario.'() {
73 given: 'service method returns a list containing a data node'
74 def dataNode = new DataNodeBuilder().withXpath('/xpath').build()
75 def cpsPath = 'some cps-path'
76 mockNetworkCmProxyDataService.queryDataNodes(cmHandle, cpsPath, expectedCpsDataServiceOption) >> [dataNode]
77 and: 'the query endpoint'
78 def dataNodeEndpoint = "$deprecatedDataNodeBaseEndPoint/cm-handles/$cmHandle/nodes/query"
79 when: 'query data nodes API is invoked'
80 def response = mvc.perform(get(dataNodeEndpoint)
81 .param('cps-path', cpsPath)
82 .param('include-descendants', includeDescendantsOption))
84 then: 'the response contains the the datanode in json format'
85 response.status == HttpStatus.OK.value()
86 def expectedJsonContent = new Gson().toJson(dataNode)
87 response.getContentAsString().contains(expectedJsonContent)
88 where: 'the following options for include descendants are provided in the request'
89 scenario | includeDescendantsOption || expectedCpsDataServiceOption
90 'no descendants by default' | '' || OMIT_DESCENDANTS
91 'no descendant explicitly' | 'false' || OMIT_DESCENDANTS
92 'descendants' | 'true' || INCLUDE_ALL_DESCENDANTS
95 def 'Create data node: #scenario.'() {
97 def jsonData = 'json data'
98 when: 'post request is performed'
99 def response = mvc.perform(
100 post("$deprecatedDataNodeBaseEndPoint/cm-handles/$cmHandle/nodes")
101 .contentType(MediaType.APPLICATION_JSON)
103 .param('xpath', reqXpath)
104 ).andReturn().response
105 then: 'the service method is invoked once with expected parameters'
106 1 * mockNetworkCmProxyDataService.createDataNode(cmHandle, usedXpath, jsonData)
107 and: 'response status indicates success'
108 response.status == HttpStatus.CREATED.value()
109 where: 'following parameters were used'
110 scenario | reqXpath || usedXpath
111 'no xpath parameter' | '' || '/'
112 'root xpath' | '/' || '/'
113 'parent node xpath' | '/xpath' || '/xpath'
116 def 'Add list-node elements.'() {
117 given: 'json data and parent node xpath'
118 def jsonData = 'json data'
119 def parentNodeXpath = 'parent node xpath'
120 when: 'post request is performed'
121 def response = mvc.perform(
122 post("$deprecatedDataNodeBaseEndPoint/cm-handles/$cmHandle/list-node")
123 .contentType(MediaType.APPLICATION_JSON)
125 .param('xpath', parentNodeXpath)
126 ).andReturn().response
127 then: 'the service method is invoked once with expected parameters'
128 1 * mockNetworkCmProxyDataService.addListNodeElements(cmHandle, parentNodeXpath, jsonData)
129 and: 'response status indicates success'
130 response.status == HttpStatus.CREATED.value()
133 def 'Update data node leaves.'() {
135 def jsonData = 'json data'
136 and: 'the query endpoint'
137 def endpoint = "$deprecatedDataNodeBaseEndPoint/cm-handles/$cmHandle/nodes"
138 when: 'patch request is performed'
139 def response = mvc.perform(
141 .contentType(MediaType.APPLICATION_JSON)
143 .param('xpath', xpath)
144 ).andReturn().response
145 then: 'the service method is invoked once with expected parameters'
146 1 * mockNetworkCmProxyDataService.updateNodeLeaves(cmHandle, xpath, jsonData)
147 and: 'response status indicates success'
148 response.status == HttpStatus.OK.value()
151 def 'Replace data node tree.'() {
153 def jsonData = 'json data'
154 and: 'the query endpoint'
155 def endpoint = "$deprecatedDataNodeBaseEndPoint/cm-handles/$cmHandle/nodes"
156 when: 'put request is performed'
157 def response = mvc.perform(
159 .contentType(MediaType.APPLICATION_JSON)
161 .param('xpath', xpath)
162 ).andReturn().response
163 then: 'the service method is invoked once with expected parameters'
164 1 * mockNetworkCmProxyDataService.replaceNodeTree(cmHandle, xpath, jsonData)
165 and: 'response status indicates success'
166 response.status == HttpStatus.OK.value()
169 def 'Get data node.'() {
170 given: 'the service returns a data node'
171 def xpath = 'some xpath'
172 def dataNode = new DataNodeBuilder().withXpath(xpath).withLeaves(["leaf": "value"]).build()
173 mockNetworkCmProxyDataService.getDataNode(cmHandle, xpath, OMIT_DESCENDANTS) >> dataNode
174 and: 'the query endpoint'
175 def endpoint = "$deprecatedDataNodeBaseEndPoint/cm-handles/$cmHandle/node"
176 when: 'get request is performed through REST API'
177 def response = mvc.perform(get(endpoint).param('xpath', xpath)).andReturn().response
178 then: 'a success response is returned'
179 response.status == HttpStatus.OK.value()
180 and: 'response contains expected leaf and value'
181 response.contentAsString.contains('"leaf":"value"')
184 def 'Register CM Handle Event' () {
186 def jsonData = TestUtils.getResourceFileContent('dmi-registration.json')
187 when: 'post request is performed'
188 def response = mvc.perform(
189 post("$ncmpDmiEndpoint/ch")
190 .contentType(MediaType.APPLICATION_JSON)
192 ).andReturn().response
193 then: 'the cm handles are registered with the service'
194 1 * mockNetworkCmProxyDataService.updateDmiPluginRegistration(_)
195 and: 'response status is created'
196 response.status == HttpStatus.CREATED.value()
199 def 'Get Resource Data from pass-through operational.' () {
200 given: 'resource data url'
201 def getUrl = "$basePath/v1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" +
202 "/testResourceIdentifier?fields=testFields&depth=5"
203 when: 'get data resource request is performed'
204 def response = mvc.perform(
206 .contentType(MediaType.APPLICATION_JSON)
207 .accept(MediaType.APPLICATION_JSON_VALUE)
208 ).andReturn().response
209 then: 'the NCMP data service is called with getResourceDataOperationalForCmHandle'
210 1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
211 'testResourceIdentifier',
215 and: 'response status is Ok'
216 response.status == HttpStatus.OK.value()
219 def 'Get Resource Data from pass-through running.' () {
220 given: 'resource data url'
221 def getUrl = "$basePath/v1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
222 "/testResourceIdentifier?fields=testFields&depth=5"
223 and: 'ncmp service returns json object'
224 mockNetworkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
225 'testResourceIdentifier',
229 when: 'get data resource request is performed'
230 def response = mvc.perform(
232 .contentType(MediaType.APPLICATION_JSON)
233 .accept(MediaType.APPLICATION_JSON_VALUE)
234 ).andReturn().response
235 then: 'response status is Ok'
236 response.status == HttpStatus.OK.value()
237 and: 'response contains valid object body'
238 response.getContentAsString() == '{valid-json}'
241 def 'Create Resource Data from pass-through running using POST.' () {
242 given: 'resource data url'
243 def getUrl = "$basePath/v1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
244 "/testResourceIdentifier"
245 when: 'get data resource request is performed'
246 def response = mvc.perform(
248 .contentType(MediaType.APPLICATION_JSON_VALUE)
249 .accept(MediaType.APPLICATION_JSON_VALUE).content('{"some-json":"value"}')
250 ).andReturn().response
251 then: 'ncmp service method to create resource called'
252 1 * mockNetworkCmProxyDataService.createResourceDataPassThroughRunningForCmHandle('testCmHandle',
253 'testResourceIdentifier', ['some-json':'value'], 'application/json;charset=UTF-8')
254 and: 'resource is created'
255 response.status == HttpStatus.CREATED.value()