2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Pantheon.tech
4 * Modifications Copyright (C) 2021 highstreet technologies GmbH
5 * Modifications Copyright (C) 2021-2022 Nordix Foundation
6 * Modifications Copyright (C) 2021-2022 Bell Canada.
7 * ================================================================================
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
20 * SPDX-License-Identifier: Apache-2.0
21 * ============LICENSE_END=========================================================
24 package org.onap.cps.ncmp.rest.controller
26 import com.fasterxml.jackson.databind.ObjectMapper
27 import org.mapstruct.factory.Mappers
28 import org.onap.cps.TestUtils
29 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
30 import org.onap.cps.ncmp.api.inventory.CmHandleState
31 import org.onap.cps.ncmp.api.inventory.CompositeState
32 import org.onap.cps.ncmp.api.inventory.DataStoreSyncState
33 import org.onap.cps.ncmp.api.inventory.LockReasonCategory
34 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
35 import org.onap.cps.ncmp.rest.controller.handlers.DatastoreType
36 import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreOperationalResourceRequestHandler
37 import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastorePassthroughOperationalResourceRequestHandler
38 import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastorePassthroughRunningResourceRequestHandler
39 import org.onap.cps.ncmp.rest.controller.handlers.NcmpDatastoreResourceRequestHandlerFactory
40 import org.onap.cps.ncmp.rest.executor.CpsNcmpTaskExecutor
41 import org.onap.cps.ncmp.rest.mapper.CmHandleStateMapper
42 import org.onap.cps.ncmp.rest.util.DeprecationHelper
43 import org.onap.cps.spi.FetchDescendantsOption
44 import org.onap.cps.spi.model.ModuleDefinition
45 import org.onap.cps.spi.model.ModuleReference
46 import org.onap.cps.utils.JsonObjectMapper
47 import org.spockframework.spring.SpringBean
48 import org.springframework.beans.factory.annotation.Autowired
49 import org.springframework.beans.factory.annotation.Value
50 import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
51 import org.springframework.http.HttpStatus
52 import org.springframework.http.MediaType
53 import org.springframework.test.web.servlet.MockMvc
54 import spock.lang.Shared
55 import spock.lang.Specification
57 import java.time.OffsetDateTime
58 import java.time.ZoneOffset
59 import java.time.format.DateTimeFormatter
61 import static org.onap.cps.ncmp.api.inventory.CompositeState.DataStores
62 import static org.onap.cps.ncmp.api.inventory.CompositeState.Operational
63 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
64 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
65 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.PATCH
66 import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.DELETE
67 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
68 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
69 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
70 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch
71 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete
73 @WebMvcTest(NetworkCmProxyController)
74 class NetworkCmProxyControllerSpec extends Specification {
76 public static final int TIMEOUT_IN_MS = 2000
77 public static final boolean NOTIFICATION_ENABLED = true
83 NetworkCmProxyDataService mockNetworkCmProxyDataService = Mock()
86 ObjectMapper objectMapper = new ObjectMapper()
89 JsonObjectMapper jsonObjectMapper = new JsonObjectMapper(objectMapper)
92 NcmpRestInputMapper ncmpRestInputMapper = Mappers.getMapper(NcmpRestInputMapper)
95 CmHandleStateMapper cmHandleStateMapper = Mappers.getMapper(CmHandleStateMapper)
98 CpsNcmpTaskExecutor spiedCpsTaskExecutor = Spy()
101 DeprecationHelper stubbedDeprecationHelper = Stub()
104 NcmpDatastoreResourceRequestHandlerFactory stubbedNcmpDatastoreResourceRequestHandlerFactory = Stub()
106 @Value('${rest.api.ncmp-base-path}/v1')
109 def requestBody = '{"some-key":"some-value"}'
113 def NO_REQUEST_ID = null
115 def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
116 .format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
119 stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
120 DatastoreType.OPERATIONAL) >>
121 new NcmpDatastoreOperationalResourceRequestHandler(
122 mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
124 stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
125 DatastoreType.PASSTHROUGH_OPERATIONAL) >>
126 new NcmpDatastorePassthroughOperationalResourceRequestHandler(
127 mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
129 stubbedNcmpDatastoreResourceRequestHandlerFactory.getNcmpDatastoreResourceRequestHandler(
130 DatastoreType.PASSTHROUGH_RUNNING) >>
131 new NcmpDatastorePassthroughRunningResourceRequestHandler(
132 mockNetworkCmProxyDataService, spiedCpsTaskExecutor, TIMEOUT_IN_MS, NOTIFICATION_ENABLED)
135 def 'Get Resource Data from pass-through operational.'() {
136 given: 'resource data url'
137 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-operational" +
138 "?resourceIdentifier=parent/child&options=(a=1,b=2)"
139 when: 'get data resource request is performed'
140 def response = mvc.perform(
142 .contentType(MediaType.APPLICATION_JSON)
143 ).andReturn().response
144 then: 'the NCMP data service is called with getResourceDataOperationalForCmHandle'
145 1 * mockNetworkCmProxyDataService.getResourceDataOperationalForCmHandle('testCmHandle',
150 and: 'response status is Ok'
151 response.status == HttpStatus.OK.value()
154 def 'Get Resource Data from #datastoreInUrl with #scenario.'() {
155 given: 'resource data url'
156 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
157 "?resourceIdentifier=parent/child&options=(a=1,b=2)${topicQueryParam}"
158 when: 'get data resource request is performed'
159 def response = mvc.perform(
160 get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response
161 then: 'task executor is called appropriate number of times'
162 expectedNumberOfExecutorExecutions * spiedCpsTaskExecutor.executeTask(_, TIMEOUT_IN_MS)
163 and: 'response status is expected'
164 response.status == HttpStatus.OK.value()
165 where: 'the following parameters are used'
166 scenario | datastoreInUrl | topicQueryParam || expectedTopicName | expectedNumberOfExecutorExecutions
167 'url with valid topic' | 'passthrough-operational' | '&topic=my-topic-name' || 'my-topic-name' | 1
168 'no topic in url' | 'passthrough-operational' | '' || NO_TOPIC | 0
169 'null topic in url' | 'passthrough-operational' | '&topic=null' || 'null' | 1
170 'url with valid topic' | 'passthrough-running' | '&topic=my-topic-name' || 'my-topic-name' | 1
171 'no topic in url' | 'passthrough-running' | '' || NO_TOPIC | 0
172 'null topic in url' | 'passthrough-running' | '&topic=null' || 'null' | 1
175 def 'Fail to get Resource Data from #datastoreInUrl when #scenario.'() {
176 given: 'resource data url'
177 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
178 "?resourceIdentifier=parent/child&options=(a=1,b=2)${topicQueryParam}"
179 when: 'get data resource request is performed'
180 def response = mvc.perform(
181 get(getUrl).contentType(MediaType.APPLICATION_JSON)).andReturn().response
182 then: 'abad request is returned'
183 response.status == HttpStatus.BAD_REQUEST.value()
184 where: 'the following parameters are used'
185 scenario | datastoreInUrl | topicQueryParam
186 'empty topic in url' | 'passthrough-operational' | '&topic=\"\"'
187 'missing topic in url' | 'passthrough-operational' | '&topic='
188 'blank topic value in url' | 'passthrough-operational' | '&topic=\" \"'
189 'invalid non-empty topic value in url' | 'passthrough-operational' | '&topic=1_5_*_#'
190 'empty topic in url' | 'passthrough-running' | '&topic=\"\"'
191 'missing topic in url' | 'passthrough-running' | '&topic='
192 'blank topic value in url' | 'passthrough-running' | '&topic=\" \"'
193 'invalid non-empty topic value in url' | 'passthrough-running' | '&topic=1_5_*_#'
196 def 'Get Resource Data from pass-through running with #scenario value in resource identifier param.'() {
197 given: 'resource data url'
198 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
199 "?resourceIdentifier=" + resourceIdentifier + "&options=(a=1,b=2)"
200 and: 'ncmp service returns json object'
201 mockNetworkCmProxyDataService.getResourceDataPassThroughRunningForCmHandle('testCmHandle',
205 NO_REQUEST_ID) >> '{valid-json}'
206 when: 'get data resource request is performed'
207 def response = mvc.perform(
209 .contentType(MediaType.APPLICATION_JSON)
210 ).andReturn().response
211 then: 'response status is Ok'
212 response.status == HttpStatus.OK.value()
213 and: 'response contains valid object body'
214 response.getContentAsString() == '{valid-json}'
215 where: 'tokens are used in the resource identifier parameter'
216 scenario | resourceIdentifier
217 '/' | 'id/with/slashes'
222 '? needs to be encoded as %3F' | 'idWith%3F'
225 def 'Update resource data from pass-through running.'() {
226 given: 'update resource data url'
227 def updateUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
228 "?resourceIdentifier=parent/child"
229 when: 'update data resource request is performed'
230 def response = mvc.perform(
232 .contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
233 ).andReturn().response
234 then: 'ncmp service method to update resource is called'
235 1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
236 'parent/child', UPDATE, requestBody, 'application/json;charset=UTF-8')
237 and: 'the response status is OK'
238 response.status == HttpStatus.OK.value()
241 def 'Create Resource Data from pass-through running with #scenario.'() {
242 given: 'resource data url'
243 def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
244 "?resourceIdentifier=parent/child"
245 def requestBody = '{"some-key":"some-value"}'
246 when: 'create resource request is performed'
247 def response = mvc.perform(
249 .contentType(MediaType.APPLICATION_JSON_VALUE).content(requestBody)
250 ).andReturn().response
251 then: 'ncmp service method to create resource called'
252 1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
253 'parent/child', CREATE, requestBody, 'application/json;charset=UTF-8')
254 and: 'resource is created'
255 response.status == HttpStatus.CREATED.value()
258 def 'Get module references for the given dataspace and cm handle.'() {
259 given: 'get module references url'
260 def getUrl = "$ncmpBasePathV1/ch/some-cmhandle/modules"
261 when: 'get module resource request is performed'
262 def response = mvc.perform(get(getUrl)).andReturn().response
263 then: 'ncmp service method to get yang resource module references is called'
264 mockNetworkCmProxyDataService.getYangResourcesModuleReferences('some-cmhandle')
265 >> [new ModuleReference(moduleName: 'some-name1', revision: '2021-10-03')]
266 and: 'response contains an array with the module name and revision'
267 response.getContentAsString() == '[{"moduleName":"some-name1","revision":"2021-10-03"}]'
268 and: 'response returns an OK http code'
269 response.status == HttpStatus.OK.value()
272 def 'Retrieve cm handles.'() {
273 given: 'an endpoint and json data'
274 def searchesEndpoint = "$ncmpBasePathV1/ch/searches"
275 String jsonString = TestUtils.getResourceFileContent('cmhandle-search.json')
276 and: 'the service method is invoked with module names and returns two cm handles'
277 def cmHandle1 = new NcmpServiceCmHandle()
278 cmHandle1.cmHandleId = 'some-cmhandle-id1'
279 cmHandle1.publicProperties = [color: 'yellow']
280 def cmHandle2 = new NcmpServiceCmHandle()
281 cmHandle2.cmHandleId = 'some-cmhandle-id2'
282 cmHandle2.publicProperties = [color: 'green']
283 mockNetworkCmProxyDataService.executeCmHandleSearch(_) >> [cmHandle1, cmHandle2]
284 when: 'the searches api is invoked'
285 def response = mvc.perform(post(searchesEndpoint)
286 .contentType(MediaType.APPLICATION_JSON)
287 .content(jsonString)).andReturn().response
288 then: 'response status returns OK'
289 response.status == HttpStatus.OK.value()
290 and: 'the expected response content is returned'
291 response.contentAsString == '[{"cmHandle":"some-cmhandle-id1","publicCmHandleProperties":[{"color":"yellow"}],"state":null},{"cmHandle":"some-cmhandle-id2","publicCmHandleProperties":[{"color":"green"}],"state":null}]'
294 def 'Get complete Cm Handle details by Cm Handle id.'() {
295 given: 'an endpoint and a cm handle'
296 def cmHandleDetailsEndpoint = "$ncmpBasePathV1/ch/some-cm-handle"
297 and: 'an existing ncmp service cm handle'
298 def cmHandleId = 'some-cm-handle'
299 def dmiProperties = [prop: 'some DMI property']
300 def publicProperties = ["public prop": 'some public property']
301 def compositeState = compositeStateTestObject()
302 def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties, compositeState: compositeState)
303 and: 'the service method is invoked with the cm handle id'
304 1 * mockNetworkCmProxyDataService.getNcmpServiceCmHandle('some-cm-handle') >> ncmpServiceCmHandle
305 when: 'the cm handle details api is invoked'
306 def response = mvc.perform(
307 get(cmHandleDetailsEndpoint)).andReturn().response
308 then: 'the correct response is returned'
309 response.status == HttpStatus.OK.value()
310 and: 'the response contains the public properties'
311 assertContainsPublicProperties(response)
312 and: 'the response contains the cm handle state'
313 assertContainsState(response)
314 and: 'the content does not contain dmi properties'
315 !response.contentAsString.contains("some DMI property")
318 def 'Get Cm Handle public properties by Cm Handle id.'() {
319 given: 'a cm handle properties endpoint'
320 def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/properties"
321 and: 'some cm handle public properties'
322 def publicProperties = ['public prop': 'some public property']
323 and: 'the service method is invoked with the cm handle id returning the cm handle public properties'
324 1 * mockNetworkCmProxyDataService
325 .getCmHandlePublicProperties('some-cm-handle') >> publicProperties
326 when: 'the cm handle properties api is invoked'
327 def response = mvc.perform(
328 get(cmHandlePropertiesEndpoint)).andReturn().response
329 then: 'the correct response is returned'
330 response.status == HttpStatus.OK.value()
331 and: 'the response contains the public properties'
332 assertContainsPublicProperties(response)
335 def 'Get Cm Handle composite state by Cm Handle id.'() {
336 given: 'a cm handle state endpoint'
337 def cmHandlePropertiesEndpoint = "$ncmpBasePathV1/ch/some-cm-handle/state"
338 and: 'some cm handle composite state'
339 def compositeState = compositeStateTestObject()
340 and: 'the service method is invoked with the cm handle id returning the cm handle composite state'
341 1 * mockNetworkCmProxyDataService
342 .getCmHandleCompositeState('some-cm-handle') >> compositeState
343 when: 'the cm handle state api is invoked'
344 def response = mvc.perform(
345 get(cmHandlePropertiesEndpoint)).andReturn().response
346 then: 'the correct response is returned'
347 response.status == HttpStatus.OK.value()
348 and: 'the response contains the cm handle state'
349 assertContainsState(response)
352 def 'Call execute cm handle searches with unrecognized condition name.'() {
353 given: 'an endpoint and json data'
354 def searchesEndpoint = "$ncmpBasePathV1/ch/searches"
355 String jsonString = TestUtils.getResourceFileContent('invalid-cmhandle-search.json')
356 and: 'the service method is invoked with module names and returns two cm handles'
357 def cmHandel1 = new NcmpServiceCmHandle()
358 cmHandel1.cmHandleId = 'some-cmhandle-id1'
359 cmHandel1.publicProperties = [color: 'yellow']
360 def cmHandel2 = new NcmpServiceCmHandle()
361 cmHandel2.cmHandleId = 'some-cmhandle-id2'
362 cmHandel2.publicProperties = [color: 'green']
363 mockNetworkCmProxyDataService.executeCmHandleSearch(_) >> [cmHandel1, cmHandel2]
364 when: 'the searches api is invoked'
365 def response = mvc.perform(
366 post(searchesEndpoint)
367 .contentType(MediaType.APPLICATION_JSON)
368 .content(jsonString)).andReturn().response
369 then: 'an empty cm handle identifier is returned'
370 response.contentAsString == '[{"cmHandle":"some-cmhandle-id1","publicCmHandleProperties":[{"color":"yellow"}],"state":null},{"cmHandle":"some-cmhandle-id2","publicCmHandleProperties":[{"color":"green"}],"state":null}]'
373 def 'Query for cm handles matching query parameters'() {
374 given: 'an endpoint and json data'
375 def searchesEndpoint = "$ncmpBasePathV1/ch/id-searches"
376 and: 'the service method is invoked with module names and returns cm handle ids'
377 1 * mockNetworkCmProxyDataService.executeCmHandleIdSearch(_) >> ['some-cmhandle-id1', 'some-cmhandle-id2']
378 when: 'the searches api is invoked'
379 def response = mvc.perform(
380 post(searchesEndpoint)
381 .contentType(MediaType.APPLICATION_JSON)
382 .content('{}')).andReturn().response
383 then: 'cm handle ids are returned'
384 response.contentAsString == '["some-cmhandle-id1","some-cmhandle-id2"]'
387 def 'Query for cm handles with invalid request payload'() {
388 when: 'the searches api is invoked'
389 def searchesEndpoint = "$ncmpBasePathV1/ch/id-searches"
390 def invalidInputData = '{invalidJson}'
391 def response = mvc.perform(
392 post(searchesEndpoint)
393 .contentType(MediaType.APPLICATION_JSON)
394 .content(invalidInputData)).andReturn().response
395 then: 'BAD_REQUEST is returned'
396 response.getStatus() == 400
399 def 'Patch resource data in pass-through running datastore.'() {
400 given: 'patch resource data url'
401 def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
402 "?resourceIdentifier=parent/child"
403 when: 'patch data resource request is performed'
404 def response = mvc.perform(
406 .contentType(MediaType.APPLICATION_JSON)
407 .accept(MediaType.APPLICATION_JSON).content(requestBody)
408 ).andReturn().response
409 then: 'ncmp service method to update resource is called'
410 1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
411 'parent/child', PATCH, requestBody, 'application/json;charset=UTF-8')
412 and: 'the response status is OK'
413 response.status == HttpStatus.OK.value()
416 def 'Delete resource data in pass-through running datastore.'() {
417 given: 'delete resource data url'
418 def url = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:passthrough-running" +
419 "?resourceIdentifier=parent/child"
420 when: 'delete data resource request is performed'
421 def response = mvc.perform(
423 .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON)).andReturn().response
424 then: 'the ncmp service method to delete resource is called (with null as body)'
425 1 * mockNetworkCmProxyDataService.writeResourceDataPassThroughRunningForCmHandle('testCmHandle',
426 'parent/child', DELETE, null, 'application/json;charset=UTF-8')
427 and: 'the response is No Content'
428 response.status == HttpStatus.NO_CONTENT.value()
431 def 'Get resource data from DMI with valid topic i.e. async request for #scenario'() {
432 given: 'resource data url'
433 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:${datastoreInUrl}" +
434 "?resourceIdentifier=parent/child&options=(a=1,b=2)&topic=my-topic-name"
435 when: 'get data resource request is performed'
436 def response = mvc.perform(
438 .contentType(MediaType.APPLICATION_JSON)
439 .accept(MediaType.APPLICATION_JSON_VALUE)
440 ).andReturn().response
441 then: 'async request id is generated'
442 assert response.contentAsString.contains("requestId")
443 where: 'the following parameters are used'
444 scenario | datastoreInUrl
445 ':passthrough-operational' | 'passthrough-operational'
446 ':passthrough-running' | 'passthrough-running'
449 def 'Get module definitions based on cmHandleId.'() {
450 when: 'get module definition request is performed'
451 def response = mvc.perform(
452 get("$ncmpBasePathV1/ch/some-cmhandle/modules/definitions"))
453 .andReturn().response
454 then: 'ncmp service method to get module definitions is called'
455 mockNetworkCmProxyDataService.getModuleDefinitionsByCmHandleId('some-cmhandle')
456 >> [new ModuleDefinition('sampleModuleName', '2021-10-03',
457 'module sampleModuleName{ sample module content }')]
458 and: 'response contains an array with the module name, revision and content'
459 response.getContentAsString() == '[{"moduleName":"sampleModuleName","revision":"2021-10-03","content":"module sampleModuleName{ sample module content }"}]'
460 and: 'response returns an OK http code'
461 response.status == HttpStatus.OK.value()
464 def 'Set the data sync enabled based on the cm handle id and the data sync flag is #scenario'() {
465 when: 'the set data sync enabled request is invoked'
466 def response = mvc.perform(
467 put("$ncmpBasePathV1/ch/some-cm-handle-id/data-sync?dataSyncEnabled=" + dataSyncEnabledFlag))
468 .andReturn().response
469 then: 'method to set data sync enabled is called'
470 1 * mockNetworkCmProxyDataService.setDataSyncEnabled('some-cm-handle-id', dataSyncEnabledFlag)
471 and: 'the response returns an OK http code'
472 response.status == HttpStatus.OK.value()
473 where: 'the following parameters are used'
474 scenario | dataSyncEnabledFlag
479 def 'Get Resource Data from operational without descendants.'() {
480 given: 'resource data url'
481 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational" +
482 "?resourceIdentifier=parent/child&include-descendants=false"
483 when: 'get data resource request is performed'
484 def response = mvc.perform(
486 .contentType(MediaType.APPLICATION_JSON)
487 ).andReturn().response
488 then: 'the NCMP data service is called with getResourceDataOperational'
489 1 * mockNetworkCmProxyDataService.getResourceDataOperational('testCmHandle',
491 FetchDescendantsOption.OMIT_DESCENDANTS)
492 and: 'response status is Ok'
493 response.status == HttpStatus.OK.value()
496 def 'Get Resource Data from operational including descendants.'() {
497 given: 'resource data url'
498 def getUrl = "$ncmpBasePathV1/ch/testCmHandle/data/ds/ncmp-datastore:operational" +
499 "?resourceIdentifier=parent/child&include-descendants=true"
500 when: 'get data resource request is performed'
501 def response = mvc.perform(
503 .contentType(MediaType.APPLICATION_JSON)
504 ).andReturn().response
505 then: 'the NCMP data service is called with getResourceDataOperational'
506 1 * mockNetworkCmProxyDataService.getResourceDataOperational('testCmHandle',
508 FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
509 and: 'response status is Ok'
510 response.status == HttpStatus.OK.value()
515 .operationalDataStore(Operational.builder()
516 .dataStoreSyncState(DataStoreSyncState.NONE_REQUESTED)
517 .lastSyncTime(formattedDateAndTime.toString()).build()).build()
520 def compositeStateTestObject() {
521 new CompositeState(cmHandleState: CmHandleState.ADVISED,
522 lockReason: CompositeState.LockReason.builder().lockReasonCategory(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED).details("lock details").build(),
523 lastUpdateTime: formattedDateAndTime.toString(),
524 dataSyncEnabled: false,
525 dataStores: dataStores())
528 def assertContainsAll(response, assertContent) {
529 assertContent.forEach(string -> { assert (response.contentAsString.contains(string)) })
533 def assertContainsState(response) {
534 def expectedContent = [
536 '"cmHandleState":"ADVISED"',
537 '"reason":"LOCKED_MISBEHAVING"',
538 '"details":"lock details"',
539 '"lastUpdateTime":"2022-12-31T20:30:40.000+0000"',
540 '"dataSyncEnabled":false',
543 '"syncState":"NONE_REQUESTED"',
544 '"lastSyncTime":"2022-12-31T20:30:40.000+0000"',
547 return assertContainsAll(response, expectedContent)
550 def assertContainsPublicProperties(response) {
551 def expectedContent = [
552 '"publicCmHandleProperties":',
554 '"some public property"'
556 return assertContainsAll(response, expectedContent)