summaryrefslogtreecommitdiffstats
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/groovy/org/onap/cps/ncmp/dmi/model/ModuleSchemaPropertiesSpec.groovy41
-rw-r--r--src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy145
-rw-r--r--src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy138
-rw-r--r--src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy17
-rw-r--r--src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy104
-rw-r--r--src/test/resources/createDataWithNormalChar.json (renamed from src/test/resources/dataWithNormalChar.json)0
-rw-r--r--src/test/resources/createDataWithSpecialChar.json (renamed from src/test/resources/dataWithSpecialChar.json)0
-rw-r--r--src/test/resources/deleteData.json8
-rw-r--r--src/test/resources/readData.json8
-rw-r--r--src/test/resources/updateData.json8
10 files changed, 270 insertions, 199 deletions
diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/model/ModuleSchemaPropertiesSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/model/ModuleSchemaPropertiesSpec.groovy
deleted file mode 100644
index 51dddc7d..00000000
--- a/src/test/groovy/org/onap/cps/ncmp/dmi/model/ModuleSchemaPropertiesSpec.groovy
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.cps.ncmp.dmi.model
-
-import org.onap.cps.ncmp.dmi.service.model.ModuleSchemaProperties
-import spock.lang.Specification
-
-class ModuleSchemaPropertiesSpec extends Specification {
- def objectUnderTest = new ModuleSchemaProperties(identifier:'some id',
- version:'some version',
- format:'some format',
- namespace:'some namespace',
- location: ['some','locations'])
-
- def 'Reading all properties.'() {
- expect: 'all properties return the expected values'
- objectUnderTest.identifier == 'some id'
- objectUnderTest.version == 'some version'
- objectUnderTest.format == 'some format'
- objectUnderTest.namespace == 'some namespace'
- objectUnderTest.location == ['some','locations']
- }
-}
diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy
index ac78928d..221603c2 100644
--- a/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy
+++ b/src/test/groovy/org/onap/cps/ncmp/dmi/rest/controller/DmiRestControllerSpec.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
+ * Modifications Copyright (C) 2021 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,7 +27,6 @@ import org.onap.cps.ncmp.dmi.exception.DmiException
import org.onap.cps.ncmp.dmi.exception.ModuleResourceNotFoundException
import org.onap.cps.ncmp.dmi.exception.ModulesNotFoundException
import org.onap.cps.ncmp.dmi.service.model.ModuleReference
-import org.onap.cps.ncmp.dmi.service.model.ModuleSchemaList
import org.onap.cps.ncmp.dmi.model.ModuleSet
import org.onap.cps.ncmp.dmi.model.ModuleSetSchemas
import org.onap.cps.ncmp.dmi.model.YangResource
@@ -35,33 +35,39 @@ import org.onap.cps.ncmp.dmi.service.DmiService
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
-import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest
+import org.springframework.context.annotation.Import
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
+import org.springframework.security.test.context.support.WithMockUser
import org.springframework.test.web.servlet.MockMvc
import spock.lang.Specification
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.DELETE
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.READ
+import static org.springframework.http.HttpStatus.BAD_REQUEST
+import static org.springframework.http.HttpStatus.NO_CONTENT
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.CREATE
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.UPDATE
+import static org.springframework.http.HttpStatus.CREATED
+import static org.springframework.http.HttpStatus.OK
-@WebMvcTest
-@AutoConfigureMockMvc(addFilters = false)
+@WebMvcTest(DmiRestController)
+@WithMockUser
+@Import(ObjectMapper)
class DmiRestControllerSpec extends Specification {
@SpringBean
DmiService mockDmiService = Mock()
- @SpringBean
- ObjectMapper mockObjectMapper = Spy()
-
@Autowired
private MockMvc mvc
@Value('${rest.api.dmi-base-path}/v1')
def basePathV1
- def 'Get all modules for given cm handle.'() {
+ def 'Get all modules.'() {
given: 'REST endpoint for getting all modules'
def getModuleUrl = "$basePathV1/ch/node1/modules"
and: 'get modules for cm-handle returns a json'
@@ -78,26 +84,12 @@ class DmiRestControllerSpec extends Specification {
.contentType(MediaType.APPLICATION_JSON).content(json))
.andReturn().response
then: 'status is OK'
- response.status == HttpStatus.OK.value()
+ response.status == OK.value()
and: 'the response content matches the result from the DMI service'
response.getContentAsString() == '{"schemas":[{"moduleName":"some-moduleName","revision":"some-revision","namespace":"some-namespace"}]}'
}
- def 'Get all modules for given cm handle with invalid json.'() {
- given: 'REST endpoint for getting all modules'
- def getModuleUrl = "$basePathV1/ch/node1/modules"
- and: 'get modules for cmHandle throws an exception'
- mockObjectMapper.readValue(_ as String, _ as ModuleSchemaList) >> { throw Mock(DmiException.class) }
- mockDmiService.getModulesForCmHandle('node1') >> 'some-value'
- when: 'post is being called'
- def response = mvc.perform(post(getModuleUrl)
- .contentType(MediaType.APPLICATION_JSON))
- .andReturn().response
- then: 'the status is as expected'
- response.status == HttpStatus.INTERNAL_SERVER_ERROR.value()
- }
-
- def 'Get all modules for given cm handle with exception handling of #scenario.'() {
+ def 'Get all modules with exception handling of #scenario.'() {
given: 'REST endpoint for getting all modules'
def getModuleUrl = "$basePathV1/ch/node1/modules"
and: 'given request body and get modules for cm-handle throws #exceptionClass'
@@ -116,20 +108,20 @@ class DmiRestControllerSpec extends Specification {
'any other runtime exception' | RuntimeException.class || HttpStatus.INTERNAL_SERVER_ERROR.value()
}
- def 'Register given list of cm handles.'() {
+ def 'Register given list.'() {
given: 'register cm handle url and cm handles json'
def registerCmhandlesPost = "${basePathV1}/inventory/cmHandles"
def cmHandleJson = '{"cmHandles":["node1", "node2"]}'
- when: 'post register cm handles api is invoked'
+ when: 'register cm handles api is invoked with POST'
def response = mvc.perform(
post(registerCmhandlesPost)
.contentType(MediaType.APPLICATION_JSON)
.content(cmHandleJson)
).andReturn().response
- then: 'register cm handles in dmi service is called once'
+ then: 'register cm handles in dmi service is invoked with correct parameters'
1 * mockDmiService.registerCmHandles(_ as List<String>)
and: 'response status is created'
- response.status == HttpStatus.CREATED.value()
+ response.status == CREATED.value()
}
def 'register cm handles called with empty content.'() {
@@ -142,7 +134,7 @@ class DmiRestControllerSpec extends Specification {
.content(emptyJson)
).andReturn().response
then: 'response status is "bad request"'
- response.status == HttpStatus.BAD_REQUEST.value()
+ response.status == BAD_REQUEST.value()
and: 'dmi service is not called'
0 * mockDmiService.registerCmHandles(_)
}
@@ -164,7 +156,7 @@ class DmiRestControllerSpec extends Specification {
.contentType(MediaType.APPLICATION_JSON)
.content(jsonData)).andReturn().response
then: 'a OK status is returned'
- response.status == HttpStatus.OK.value()
+ response.status == OK.value()
and: 'the expected response is returned'
response.getContentAsString() == '[{"yangSource":"\\"some-data\\"","moduleName":"NAME","revision":"REVISION"}]'
}
@@ -183,68 +175,105 @@ class DmiRestControllerSpec extends Specification {
response.status == HttpStatus.NOT_FOUND.value()
}
- def 'Get resource data for pass-through operational from cm handle.'() {
+ def 'Get resource data for pass-through operational.'() {
given: 'Get resource data url'
def getResourceDataForCmHandleUrl = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-operational" +
"?resourceIdentifier=parent/child&options=(fields=myfields,depth=5)"
def json = '{"cmHandleProperties" : { "prop1" : "value1", "prop2" : "value2"}}'
- when: 'get resource data PUT api is invoked'
+ when: 'get resource data POST api is invoked'
def response = mvc.perform(
- put(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON)
+ post(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON).content(json)
).andReturn().response
then: 'response status is ok'
- response.status == HttpStatus.OK.value()
- and: 'dmi service called with get resource data for cm handle'
- 1 * mockDmiService.getResourceDataOperationalForCmHandle('some-cmHandle',
+ response.status == OK.value()
+ and: 'dmi service called with get resource data'
+ 1 * mockDmiService.getResourceData('some-cmHandle',
'parent/child',
'application/json',
'(fields=myfields,depth=5)',
- ['prop1': 'value1', 'prop2': 'value2'])
+ 'content=all')
+ }
+
+ def 'Get resource data for pass-through operational with bad request.'() {
+ given: 'Get resource data url'
+ def getResourceDataForCmHandleUrl = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-operational" +
+ "?resourceIdentifier=parent/child&options=(fields=myfields,depth=5)"
+ def jsonData = TestUtils.getResourceFileContent('createDataWithNormalChar.json')
+ when: 'get resource data POST api is invoked'
+ def response = mvc.perform(
+ post(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON).content(jsonData)
+ ).andReturn().response
+ then: 'response status is bad request'
+ response.status == BAD_REQUEST.value()
+ and: 'dmi service is not invoked'
+ 0 * mockDmiService.getResourceData(*_)
}
- def 'Write data using passthrough running for a cm handle using #scenario.'() {
- given: 'write data for cmHandle url and jsonData'
- def writeDataforCmHandlePassthroughRunning = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" +
+ def 'write data with #scenario operation using passthrough running.'() {
+ given: 'write data for passthrough running url and jsonData'
+ def writeDataForPassthroughRunning = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" +
"?resourceIdentifier=some-resourceIdentifier"
def jsonData = TestUtils.getResourceFileContent(requestBodyFile)
and: 'dmi service is called'
- mockDmiService.writeResourceDataPassthroughForCmHandle('some-cmHandle',
+ mockDmiService.writeData(operationEnum, 'some-cmHandle',
'some-resourceIdentifier', 'application/json',
- expectedRequestData) >> '{some-json}'
- when: 'write cmHandle passthrough running post api is invoked with json data'
+ 'normal request body' ) >> '{some-json}'
+ when: 'write data for passthrough running post api is invoked with json data'
def response = mvc.perform(
- post(writeDataforCmHandlePassthroughRunning).contentType(MediaType.APPLICATION_JSON)
+ post(writeDataForPassthroughRunning).contentType(MediaType.APPLICATION_JSON)
.content(jsonData)
).andReturn().response
- then: 'response status is 201 CREATED'
- response.status == HttpStatus.CREATED.value()
+ then: 'response status is #expectedResponseStatus'
+ response.status == expectedResponseStatus
and: 'the data in the request body is as expected'
- response.getContentAsString() == '{some-json}'
+ response.getContentAsString() == expectedJsonResponse
where: 'given request body and data'
- scenario | requestBodyFile || expectedRequestData
- 'data with normal chars' | 'dataWithNormalChar.json' || 'normal request body'
- 'data with special chars' | 'dataWithSpecialChar.json'|| 'data with quote \" and new line \n'
+ scenario | requestBodyFile | operationEnum || expectedResponseStatus | expectedJsonResponse
+ 'Create' | 'createDataWithNormalChar.json' | CREATE || CREATED.value() | '{some-json}'
+ 'Update' | 'updateData.json' | UPDATE || OK.value() | '{some-json}'
+ 'Delete' | 'deleteData.json' | DELETE || NO_CONTENT.value() | '{some-json}'
+ 'Read' | 'readData.json' | READ || OK.value() | ''
}
- def 'Get resource data for pass-through running from cm handle with #scenario value in resource identifier param.'() {
+ def 'Create data using passthrough for special characters.'(){
+ given: 'create data for cmHandle url and JsonData'
+ def writeDataForCmHandlePassthroughRunning = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" +
+ "?resourceIdentifier=some-resourceIdentifier"
+ def jsonData = TestUtils.getResourceFileContent('createDataWithSpecialChar.json')
+ and: 'dmi service is called'
+ mockDmiService.writeData(CREATE, 'some-cmHandle', 'some-resourceIdentifier', 'application/json',
+ 'data with quote \" and new line \n') >> '{some-json}'
+ when: 'create cmHandle passthrough running post api is invoked with json data with special chars'
+ def response = mvc.perform(
+ post(writeDataForCmHandlePassthroughRunning).contentType(MediaType.APPLICATION_JSON).content(jsonData)
+ ).andReturn().response
+ then: 'response status is CREATED'
+ response.status == CREATED.value()
+ and: 'the data in the request body is as expected'
+ response.getContentAsString() == '{some-json}'
+ }
+
+
+ def 'Get resource data for pass-through running with #scenario value in resource identifier param.'() {
given: 'Get resource data url'
def getResourceDataForCmHandleUrl = "${basePathV1}/ch/some-cmHandle/data/ds/ncmp-datastore:passthrough-running" +
"?resourceIdentifier="+resourceIdentifier+"&options=(fields=myfields,depth=5)"
def json = '{"cmHandleProperties" : { "prop1" : "value1", "prop2" : "value2"}}'
- when: 'get resource data PUT api is invoked'
+ when: 'get resource data POST api is invoked'
def response = mvc.perform(
- put(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON)
+ post(getResourceDataForCmHandleUrl).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON).content(json)
).andReturn().response
then: 'response status is ok'
- response.status == HttpStatus.OK.value()
- and: 'dmi service called with get resource data for cm handle'
- 1 * mockDmiService.getResourceDataPassThroughRunningForCmHandle('some-cmHandle',
+ response.status == OK.value()
+ and: 'dmi service called with get resource data for a cm handle'
+ 1 * mockDmiService.getResourceData('some-cmHandle',
resourceIdentifier,
'application/json',
'(fields=myfields,depth=5)',
- ['prop1':'value1', 'prop2':'value2'])
+ 'content=config')
where: 'tokens are used in the resource identifier parameter'
scenario | resourceIdentifier
'/' | 'id/with/slashes'
diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy
index 9325d59b..a463a344 100644
--- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy
+++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/DmiServiceImplSpec.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
+ * Modifications Copyright (C) 2021 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,7 +24,6 @@ package org.onap.cps.ncmp.dmi.service
import com.fasterxml.jackson.core.JsonProcessingException
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectWriter
-import org.onap.cps.ncmp.dmi.TestUtils
import org.onap.cps.ncmp.dmi.config.DmiPluginConfig
import org.onap.cps.ncmp.dmi.exception.CmHandleRegistrationException
import org.onap.cps.ncmp.dmi.exception.DmiException
@@ -34,11 +34,15 @@ import org.onap.cps.ncmp.dmi.service.model.ModuleReference
import org.onap.cps.ncmp.dmi.model.YangResource
import org.onap.cps.ncmp.dmi.model.YangResources
import org.onap.cps.ncmp.dmi.service.client.NcmpRestClient
+import org.onap.cps.ncmp.dmi.service.model.ModuleSchema
import org.onap.cps.ncmp.dmi.service.operation.SdncOperations
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import spock.lang.Specification
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.CREATE
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.UPDATE
+
class DmiServiceImplSpec extends Specification {
@@ -49,50 +53,35 @@ class DmiServiceImplSpec extends Specification {
def mockSdncOperations = Mock(SdncOperations)
def objectUnderTest = new DmiServiceImpl(mockDmiPluginProperties, mockNcmpRestClient, mockSdncOperations, spyObjectMapper)
- def 'Call get modules for cm-handle on dmi Service.'() {
- given: 'cm handle id'
- def cmHandle = 'node1'
- and: 'request operation returns OK'
- def body = TestUtils.getResourceFileContent('ModuleSchema.json')
- mockSdncOperations.getModulesFromNode(cmHandle) >> new ResponseEntity<String>(body, HttpStatus.OK)
- when: 'get modules for cm-handle is called'
- def result = objectUnderTest.getModulesForCmHandle(cmHandle)
- then: 'result is equal to the response from the SDNC service'
- result.toString().contains('moduleName: example-identifier')
- result.toString().contains('revision: example-version')
- }
-
- def 'Call get modules for cm-handle with invalid json.'() {
- given: 'cm handle id'
+ def ' Get modules for a cm-handle.'() {
+ given: 'a cm handle'
def cmHandle = 'node1'
- and: 'request operation returns invalid json'
- def body = TestUtils.getResourceFileContent('ModuleSchema.json')
- mockSdncOperations.getModulesFromNode(cmHandle) >> new ResponseEntity<String>('invalid json', HttpStatus.OK)
+ and: 'sdnc operations returns one module schema for the cmhandle'
+ def moduleSchema = new ModuleSchema(
+ identifier: "example-identifier",
+ namespace: "example:namespace",
+ version: "example-version")
+ mockSdncOperations.getModuleSchemasFromNode(cmHandle) >> List.of(moduleSchema)
when: 'get modules for cm-handle is called'
def result = objectUnderTest.getModulesForCmHandle(cmHandle)
- then: 'a dmi exception is thrown'
- thrown(DmiException)
- }
-
- def 'Call get modules for cm-handle and SDNC returns "bad request" status.'() {
- given: 'cm handle id'
- def cmHandle = 'node1'
- and: 'get modules from node returns "bad request" status'
- mockSdncOperations.getModulesFromNode(cmHandle) >> new ResponseEntity<String>('body', HttpStatus.BAD_REQUEST)
- when: 'get modules for cm-handle is called'
- objectUnderTest.getModulesForCmHandle(cmHandle)
- then: 'dmi exception is thrown'
- thrown(DmiException)
+ then: 'one module is returned'
+ result.schemas.size() == 1
+ and: 'module has expected values'
+ with(result.schemas[0]) {
+ it.getRevision() == moduleSchema.getVersion()
+ it.getModuleName() == moduleSchema.getIdentifier()
+ it.getNamespace() == moduleSchema.getNamespace();
+ }
}
- def 'Call get modules for cm-handle and SDNC returns OK with empty body.'() {
+ def 'no modules found for the cmhandle.'() {
given: 'cm handle id'
def cmHandle = 'node1'
- and: 'get modules for cm-handle returns OK with empty body'
- mockSdncOperations.getModulesFromNode(cmHandle) >> new ResponseEntity<String>('', HttpStatus.OK)
+ and: 'sdnc operations returns no modules'
+ mockSdncOperations.getModuleSchemasFromNode(cmHandle) >> Collections.emptyList();
when: 'get modules for cm-handle is called'
objectUnderTest.getModulesForCmHandle(cmHandle)
- then: 'ModulesNotFoundException is thrown'
+ then: 'module not found exception is thrown'
thrown(ModulesNotFoundException)
}
@@ -140,14 +129,14 @@ class DmiServiceImplSpec extends Specification {
def 'Get multiple module resources.'() {
given: 'a cmHandle and module reference list'
def cmHandle = 'some-cmHandle'
- def moduleReference1 = new ModuleReference(name: 'name-1',revision: 'revision-1')
- def moduleReference2 = new ModuleReference(name: 'name-2',revision: 'revision-2')
+ def moduleReference1 = new ModuleReference(name: 'name-1', revision: 'revision-1')
+ def moduleReference2 = new ModuleReference(name: 'name-2', revision: 'revision-2')
def moduleList = [moduleReference1, moduleReference2]
when: 'get module resources is invoked with the given cm handle and a module list'
def result = objectUnderTest.getModuleResources(cmHandle, moduleList)
then: 'get modules resources is called twice'
2 * mockSdncOperations.getModuleResource(cmHandle, _) >>> [new ResponseEntity<String>('{"ietf-netconf-monitoring:output": {"data": "some-data1"}}', HttpStatus.OK),
- new ResponseEntity<String>('{"ietf-netconf-monitoring:output": {"data": "some-data2"}}', HttpStatus.OK)]
+ new ResponseEntity<String>('{"ietf-netconf-monitoring:output": {"data": "some-data2"}}', HttpStatus.OK)]
and: 'the result is a yang resources object with the expected names, revisions and yang-sources'
def yangResources = new YangResources()
def yangResource1 = new YangResource(yangSource: '"some-data1"', moduleName: 'name-1', revision: 'revision-1')
@@ -160,7 +149,7 @@ class DmiServiceImplSpec extends Specification {
def 'Get a module resource with module resource not found exception for #scenario.'() {
given: 'a cmHandle and module reference list'
def cmHandle = 'some-cmHandle'
- def moduleReference = new ModuleReference(name: 'NAME',revision: 'REVISION')
+ def moduleReference = new ModuleReference(name: 'NAME', revision: 'REVISION')
def moduleList = [moduleReference]
when: 'get module resources is invoked with the given cm handle and a module list'
objectUnderTest.getModuleResources(cmHandle, moduleList)
@@ -205,8 +194,8 @@ class DmiServiceImplSpec extends Specification {
thrownException.cause == jsonProcessingException
}
- def 'Get resource data for pass through operational from cm handle.'() {
- given: 'cm-handle, pass through parameter, resourceId, accept header, fields, depth'
+ def 'Get resource data for passthrough operational.'() {
+ given: 'cm-handle, passthrough parameter, resourceId, accept header, fields, depth'
def cmHandle = 'testCmHandle'
def resourceId = 'testResourceId'
def acceptHeaderParam = 'testAcceptParam'
@@ -215,31 +204,32 @@ class DmiServiceImplSpec extends Specification {
and: 'sdnc operation returns OK response'
mockSdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceId, optionsParam, acceptHeaderParam, contentQuery) >> new ResponseEntity<>('response json', HttpStatus.OK)
when: 'get resource data from cm handles service method invoked'
- def response = objectUnderTest.getResourceDataOperationalForCmHandle(cmHandle,
- resourceId, acceptHeaderParam,
- optionsParam, null)
+ def response = objectUnderTest.getResourceData(cmHandle,
+ resourceId, acceptHeaderParam,
+ optionsParam, contentQuery)
then: 'response have expected json'
response == 'response json'
}
- def 'Get resource data from cm handle with exception.'() {
- given: 'cm-handle, pass through parameter, resourceId, accept header, fields, depth'
+ def 'Get resource data with not found exception.'() {
+ given: 'cm-handle, passthrough parameter, resourceId, accept header, fields, depth, query param'
def cmHandle = 'testCmHandle'
def resourceId = 'testResourceId'
def acceptHeaderParam = 'testAcceptParam'
def optionsParam = '(fields=x/y/z,depth=10,test=abc)'
+ def restConfQueryParam = 'content=config'
and: 'sdnc operation returns "NOT_FOUND" response'
mockSdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceId, optionsParam, acceptHeaderParam, _ as String) >> new ResponseEntity<>(HttpStatus.NOT_FOUND)
when: 'get resource data from cm handles service method invoked'
- objectUnderTest.getResourceDataOperationalForCmHandle(cmHandle,
- resourceId, acceptHeaderParam,
- optionsParam, null)
+ objectUnderTest.getResourceData(cmHandle,
+ resourceId, acceptHeaderParam,
+ optionsParam, restConfQueryParam)
then: 'resource data not found'
thrown(ResourceDataNotFound.class)
}
- def 'Get resource data for pass through running from cm handle.'() {
- given: 'cm-handle, pass through parameter, resourceId, accept header, fields, depth'
+ def 'Get resource data for passthrough running.'() {
+ given: 'cm-handle, passthrough parameter, resourceId, accept header, fields, depth'
def cmHandle = 'testCmHandle'
def resourceId = 'testResourceId'
def acceptHeaderParam = 'testAcceptParam'
@@ -247,50 +237,46 @@ class DmiServiceImplSpec extends Specification {
def contentQuery = 'content=config'
and: 'sdnc operation returns OK response'
mockSdncOperations.getResouceDataForOperationalAndRunning(cmHandle, resourceId, optionsParam,
- acceptHeaderParam, contentQuery) >> new ResponseEntity<>('response json', HttpStatus.OK)
+ acceptHeaderParam, contentQuery) >> new ResponseEntity<>('response json', HttpStatus.OK)
when: 'get resource data from cm handles service method invoked'
- def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle(cmHandle,
- resourceId, acceptHeaderParam,
- optionsParam, null)
+ def response = objectUnderTest.getResourceData(cmHandle,
+ resourceId, acceptHeaderParam,
+ optionsParam, contentQuery)
then: 'response have expected json'
response == 'response json'
}
- def 'Write resource data for passthrough running for the given cm handle with a #scenario from sdnc.'() {
+ def 'Write resource data for passthrough running with a #scenario from sdnc.'() {
given: 'sdnc returns a response with #scenario'
- mockSdncOperations.writeResourceDataPassthroughRunning(_, _, _, _) >> new ResponseEntity<String>('response json', httpResponse)
+ mockSdncOperations.writeData(operationEnum, _, _, _, _) >> new ResponseEntity<String>('response json', httpResponse)
when: 'write resource data for cm handle method invoked'
- def response = objectUnderTest.writeResourceDataPassthroughForCmHandle('some-cmHandle',
- 'some-resourceIdentifier', 'some-dataType', '{some-data}')
+ def response = objectUnderTest.writeData(operationEnum,'some-cmHandle',
+ 'some-resourceIdentifier', 'some-dataType', '{some-data}')
then: 'the response contains the expected json data from sdnc'
response == 'response json'
where: 'the following values are used'
- scenario | httpResponse
- '200 OK response' | HttpStatus.OK
- '201 CREATED response' | HttpStatus.CREATED
+ scenario | httpResponse | operationEnum
+ '200 OK with an update operation' | HttpStatus.OK | UPDATE
+ '201 CREATED with a create operation' | HttpStatus.CREATED | CREATE
}
- def 'Write resource data using for passthrough running for the given cm handle with #scenario.'() {
+ def 'Write resource data with special characters.'() {
given: 'sdnc returns a created response'
- mockSdncOperations.writeResourceDataPassthroughRunning('some-cmHandle',
- 'some-resourceIdentifier', 'some-dataType', requestBody) >> new ResponseEntity<String>('response json', HttpStatus.CREATED)
+ mockSdncOperations.writeData(CREATE, 'some-cmHandle',
+ 'some-resourceIdentifier', 'some-dataType', 'data with quote " and \n new line') >> new ResponseEntity<String>('response json', HttpStatus.CREATED)
when: 'write resource data from cm handles service method invoked'
- def response = objectUnderTest.writeResourceDataPassthroughForCmHandle('some-cmHandle',
- 'some-resourceIdentifier', 'some-dataType', requestBody)
+ def response = objectUnderTest.writeData(CREATE, 'some-cmHandle',
+ 'some-resourceIdentifier', 'some-dataType', 'data with quote " and \n new line')
then: 'response have expected json'
response == 'response json'
- where: 'given request body'
- scenario | requestBody
- 'data contains normal char' | 'normal char string'
- 'data contains quote and new line' | 'data with quote " and \n new line'
}
def 'Write resource data for passthrough running with a 500 response from sdnc.'() {
given: 'sdnc returns a 500 response for the write operation'
- mockSdncOperations.writeResourceDataPassthroughRunning(_, _, _, _) >> new ResponseEntity<String>('response json', HttpStatus.INTERNAL_SERVER_ERROR)
- when: 'write resource data for pass through method is invoked'
- objectUnderTest.writeResourceDataPassthroughForCmHandle('some-cmHandle',
- 'some-resourceIdentifier', 'some-dataType', _ as String)
+ mockSdncOperations.writeData(CREATE, _, _, _, _) >> new ResponseEntity<String>('response json', HttpStatus.INTERNAL_SERVER_ERROR)
+ when: 'write resource data for passthrough method is invoked'
+ objectUnderTest.writeData(CREATE, 'some-cmHandle',
+ 'some-resourceIdentifier', 'some-dataType', _ as String)
then: 'a dmi exception is thrown'
thrown(DmiException.class)
}
diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy
index 2184c7e7..8a3170b4 100644
--- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy
+++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/client/SdncRestconfClientSpec.groovy
@@ -28,6 +28,11 @@ import org.springframework.http.ResponseEntity
import org.springframework.web.client.RestTemplate
import spock.lang.Specification
+import static org.springframework.http.HttpMethod.GET
+import static org.springframework.http.HttpMethod.POST
+import static org.springframework.http.HttpMethod.DELETE
+import static org.springframework.http.HttpMethod.PUT
+
class SdncRestconfClientSpec extends Specification {
def mockSdncProperties = Mock(DmiConfiguration.SdncProperties)
@@ -49,7 +54,7 @@ class SdncRestconfClientSpec extends Specification {
result == mockResponseEntity
}
- def 'SDNC POST operation called.'() {
+ def 'SDNC #scenario operation called.'() {
given: 'json data'
def jsonData = 'some-json'
and: 'a url for get module resources'
@@ -59,12 +64,18 @@ class SdncRestconfClientSpec extends Specification {
and: 'the rest template returns a valid response entity'
def mockResponseEntity = Mock(ResponseEntity)
when: 'get module resources is invoked'
- def result = objectUnderTest.postOperationWithJsonData(getModuleResourceUrl, jsonData, new HttpHeaders())
+ def result = objectUnderTest.httpOperationWithJsonData(expectedHttpMethod, getModuleResourceUrl, jsonData, new HttpHeaders())
then: 'the rest template is called with the correct uri and json in the body'
1 * mockRestTemplate.exchange({ it.toString() == 'http://some-uri/getModuleResourceUrl' },
- HttpMethod.POST, { it.body.contains(jsonData) }, String.class) >> mockResponseEntity
+ expectedHttpMethod, { it.body.contains(jsonData) }, String.class) >> mockResponseEntity
and: 'the output of the method is the same as the output from the test template'
result == mockResponseEntity
+ where: 'the following values are used'
+ scenario || expectedHttpMethod
+ 'POST' || POST
+ 'PUT' || PUT
+ 'GET' || GET
+ 'DELETE' || DELETE
}
def 'SDNC GET operation with header.'() {
diff --git a/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy b/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy
index 4411971a..5079ada7 100644
--- a/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy
+++ b/src/test/groovy/org/onap/cps/ncmp/dmi/service/operation/SdncOperationsSpec.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2021 Nordix Foundation
+ * Modifications Copyright (C) 2021 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,15 +21,25 @@
package org.onap.cps.ncmp.dmi.service.operation
+import org.onap.cps.ncmp.dmi.TestUtils
import org.onap.cps.ncmp.dmi.config.DmiConfiguration
+import org.onap.cps.ncmp.dmi.exception.SdncException
import org.onap.cps.ncmp.dmi.service.client.SdncRestconfClient
import org.spockframework.spring.SpringBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.http.HttpHeaders
+import org.springframework.http.HttpMethod
+import org.springframework.http.HttpStatus
+import org.springframework.http.ResponseEntity
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.CREATE
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.DELETE
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.UPDATE
+import static org.onap.cps.ncmp.dmi.model.DataAccessRequest.OperationEnum.READ
+
@SpringBootTest
@ContextConfiguration(classes = [DmiConfiguration.SdncProperties, SdncOperations])
class SdncOperationsSpec extends Specification {
@@ -39,14 +50,59 @@ class SdncOperationsSpec extends Specification {
@Autowired
SdncOperations objectUnderTest
- def 'call get modules from node to SDNC.'() {
+ def 'get modules from node.'() {
given: 'node id and url'
def nodeId = 'node1'
def expectedUrl = '/rests/data/network-topology:network-topology/topology=test-topology/node=node1/yang-ext:mount/ietf-netconf-monitoring:netconf-state/schemas'
- when: 'called get modules from node'
- objectUnderTest.getModulesFromNode(nodeId)
- then: 'the get operation is executed with the correct URL'
- 1 * mockSdncRestClient.getOperation(expectedUrl)
+ and: 'sdnc returns one module in response'
+ mockSdncRestClient.getOperation(expectedUrl) >>
+ ResponseEntity.ok(TestUtils.getResourceFileContent('ModuleSchema.json'))
+ when: 'get modules from node is called'
+ def moduleSchemas = objectUnderTest.getModuleSchemasFromNode(nodeId)
+ then: 'one module is found'
+ moduleSchemas.size() == 1
+ and: 'module schema has expected values'
+ with(moduleSchemas[0]) {
+ it.getIdentifier() == "example-identifier"
+ it.getNamespace() == "example:namespace"
+ it.getVersion() == "example-version"
+ it.getFormat() == "example-format"
+ it.getLocation() == ["example-location"]
+ }
+ }
+
+ def 'No modules from Node: SDNC Response - #scenario .'() {
+ given: 'node id and url'
+ def nodeId = 'node1'
+ def expectedUrl = '/rests/data/network-topology:network-topology/topology=test-topology/node=node1/yang-ext:mount/ietf-netconf-monitoring:netconf-state/schemas'
+ and: 'sdnc operation returns #scenario'
+ mockSdncRestClient.getOperation(expectedUrl) >> ResponseEntity.ok(responseBody)
+ when: 'modules from node is called'
+ def moduleSchemas = objectUnderTest.getModuleSchemasFromNode(nodeId)
+ then: 'no modules are returned'
+ moduleSchemas.size() == 0
+ where:
+ scenario | responseBody
+ 'empty response body ' | ''
+ 'no module schema' | '{ "ietf-netconf-monitoring:schemas" : { "schema" : [] } } '
+ }
+
+ def 'Error handling - modules from node: #scenario'() {
+ given: 'node id and url'
+ def nodeId = 'node1'
+ def expectedUrl = '/rests/data/network-topology:network-topology/topology=test-topology/node=node1/yang-ext:mount/ietf-netconf-monitoring:netconf-state/schemas'
+ and: 'sdnc operation returns configured response'
+ mockSdncRestClient.getOperation(expectedUrl) >> new ResponseEntity<>(sdncResponseBody, sdncHttpStatus)
+ when: 'modules for node are fetched'
+ objectUnderTest.getModuleSchemasFromNode(nodeId)
+ then: 'SDNCException is thrown'
+ def thrownException = thrown(SdncException)
+ thrownException.getDetails().contains(expectedExceptionDetails)
+ where:
+ scenario | sdncHttpStatus | sdncResponseBody || expectedExceptionDetails
+ 'failed response from SDNC' | HttpStatus.BAD_REQUEST | '{ "errorMessage" : "incorrect input"}' || '{ "errorMessage" : "incorrect input"}'
+ 'invalid json response' | HttpStatus.OK | 'invalid-json' || 'SDNC response is not in the expected format'
+ 'response in unexpected json schema' | HttpStatus.OK | '{ "format" : "incorrect" }' || 'SDNC response is not in the expected format'
}
def 'Get module resources from SDNC.'() {
@@ -56,7 +112,7 @@ class SdncOperationsSpec extends Specification {
when: 'get module resources is called with the expected parameters'
objectUnderTest.getModuleResource(nodeId, 'some-json-data')
then: 'the SDNC Rest client is invoked with the correct URL and json data'
- 1 * mockSdncRestClient.postOperationWithJsonData(expectedUrl, 'some-json-data', _ as HttpHeaders)
+ 1 * mockSdncRestClient.httpOperationWithJsonData(HttpMethod.POST, expectedUrl, 'some-json-data', _ as HttpHeaders)
}
def 'Get resource data from node to SDNC.'() {
@@ -64,39 +120,45 @@ class SdncOperationsSpec extends Specification {
def expectedUrl = '/rests/data/network-topology:network-topology/topology=test-topology/node=node1/yang-ext:mount/testResourceId?a=1&b=2&content=testContent'
when: 'called get modules from node'
objectUnderTest.getResouceDataForOperationalAndRunning('node1', 'testResourceId',
- '(a=1,b=2)', 'testAcceptParam', 'content=testContent')
+ '(a=1,b=2)', 'testAcceptParam', 'content=testContent')
then: 'the get operation is executed with the correct URL'
1 * mockSdncRestClient.getOperation(expectedUrl, _ as HttpHeaders)
}
- def 'Write resource data to SDNC.'() {
+ def 'Write resource data with #scenario operation to SDNC.'() {
given: 'expected url, topology-id, sdncOperation object'
def expectedUrl = '/rests/data/network-topology:network-topology/topology=test-topology/node=node1/yang-ext:mount/testResourceId'
- when: 'write resource data for pass through running is called'
- objectUnderTest.writeResourceDataPassthroughRunning('node1','testResourceId','application/json','requestData')
- then: 'the post operation is executed with the correct URL and data'
- 1 * mockSdncRestClient.postOperationWithJsonData(expectedUrl, 'requestData', _ as HttpHeaders)
+ when: 'write resource data for passthrough running is called'
+ objectUnderTest.writeData(operationEnum, 'node1', 'testResourceId', 'application/json', 'requestData')
+ then: 'the #expectedHttpMethod operation is executed with the correct URL and data'
+ 1 * mockSdncRestClient.httpOperationWithJsonData(expectedHttpMethod, expectedUrl, 'requestData', _ as HttpHeaders)
+ where: 'the following values are used'
+ scenario | operationEnum || expectedHttpMethod
+ 'Create' | CREATE || HttpMethod.POST
+ 'Update' | UPDATE || HttpMethod.PUT
+ 'Read' | READ || HttpMethod.GET
+ 'Delete' | DELETE || HttpMethod.DELETE
}
def 'build query param list for SDNC where options contains a #scenario'() {
when: 'build query param list is called with #scenario'
- def result = objectUnderTest.buildQueryParamList(optionsParamInQuery,'d=4')
+ def result = objectUnderTest.buildQueryParamList(optionsParamInQuery, 'd=4')
then: 'result equals to expected result'
result == expectedResult
where: 'following parameters are used'
- scenario | optionsParamInQuery || expectedResult
- 'single key-value pair' | '(a=x)' || ['a=x','d=4']
- 'multiple key-value pairs'| '(a=x,b=y,c=z)' || ['a=x','b=y','c=z','d=4']
- '/ as special char' | '(a=x,b=y,c=t/z)' || ['a=x','b=y','c=t/z','d=4']
- '" as special char' | '(a=x,b=y,c="z")' || ['a=x','b=y','c="z"','d=4']
- '[] as special char' | '(a=x,b=y,c=[z])' || ['a=x','b=y','c=[z]','d=4']
- '= in value' | '(a=(x=y),b=x=y)' || ['a=(x=y)','b=x=y','d=4']
+ scenario | optionsParamInQuery || expectedResult
+ 'single key-value pair' | '(a=x)' || ['a=x', 'd=4']
+ 'multiple key-value pairs' | '(a=x,b=y,c=z)' || ['a=x', 'b=y', 'c=z', 'd=4']
+ '/ as special char' | '(a=x,b=y,c=t/z)' || ['a=x', 'b=y', 'c=t/z', 'd=4']
+ '" as special char' | '(a=x,b=y,c="z")' || ['a=x', 'b=y', 'c="z"', 'd=4']
+ '[] as special char' | '(a=x,b=y,c=[z])' || ['a=x', 'b=y', 'c=[z]', 'd=4']
+ '= in value' | '(a=(x=y),b=x=y)' || ['a=(x=y)', 'b=x=y', 'd=4']
}
def 'options parameters contains a comma #scenario'() {
// https://jira.onap.org/browse/CPS-719
when: 'build query param list is called with #scenario'
- def result = objectUnderTest.buildQueryParamList(optionsParamInQuery,'d=4')
+ def result = objectUnderTest.buildQueryParamList(optionsParamInQuery, 'd=4')
then: 'expect 2 elements from options +1 from content query param (2+1) = 3 elements'
def expectedNoOfElements = 3
and: 'results contains more elements than expected'
diff --git a/src/test/resources/dataWithNormalChar.json b/src/test/resources/createDataWithNormalChar.json
index 31cdf1c5..31cdf1c5 100644
--- a/src/test/resources/dataWithNormalChar.json
+++ b/src/test/resources/createDataWithNormalChar.json
diff --git a/src/test/resources/dataWithSpecialChar.json b/src/test/resources/createDataWithSpecialChar.json
index 1e7622ee..1e7622ee 100644
--- a/src/test/resources/dataWithSpecialChar.json
+++ b/src/test/resources/createDataWithSpecialChar.json
diff --git a/src/test/resources/deleteData.json b/src/test/resources/deleteData.json
new file mode 100644
index 00000000..2233fa01
--- /dev/null
+++ b/src/test/resources/deleteData.json
@@ -0,0 +1,8 @@
+{
+ "operation": "delete",
+ "dataType": "application/json",
+ "data": "normal request body",
+ "cmHandleProperties": {
+ "some-property": "some-property-value"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/readData.json b/src/test/resources/readData.json
new file mode 100644
index 00000000..9f2b154f
--- /dev/null
+++ b/src/test/resources/readData.json
@@ -0,0 +1,8 @@
+{
+ "operation": "read",
+ "dataType": "application/json",
+ "data": "normal request body",
+ "cmHandleProperties": {
+ "some-property": "some-property-value"
+ }
+} \ No newline at end of file
diff --git a/src/test/resources/updateData.json b/src/test/resources/updateData.json
new file mode 100644
index 00000000..7cbf4f0c
--- /dev/null
+++ b/src/test/resources/updateData.json
@@ -0,0 +1,8 @@
+{
+ "operation": "update",
+ "dataType": "application/json",
+ "data": "normal request body",
+ "cmHandleProperties": {
+ "some-property": "some-property-value"
+ }
+} \ No newline at end of file