X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=cps-rest%2Fsrc%2Ftest%2Fgroovy%2Forg%2Fonap%2Fcps%2Frest%2Fcontroller%2FAdminRestControllerSpec.groovy;h=f81efd669896aa4feb1f358f5d084467095922b0;hb=6f7f589382f15c4dbfad52c1f69882beea28f05f;hp=ca99743ca8dce166ce54793924ac9be8023effb7;hpb=53f07ac2f4b3699b685b8d009c8949e81fa154a6;p=cps.git diff --git a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy index ca99743ca..f81efd669 100755 --- a/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy +++ b/cps-rest/src/test/groovy/org/onap/cps/rest/controller/AdminRestControllerSpec.groovy @@ -1,14 +1,16 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2020 Pantheon.tech - * Modifications Copyright (C) 2020 Bell Canada. All rights reserved. - * Copyright (C) 2021 Nordix Foundation + * Copyright (C) 2020-2021 Pantheon.tech + * Modifications Copyright (C) 2020-2021 Bell Canada. + * Modifications Copyright (C) 2021-2022 Nordix Foundation + * Modifications Copyright (C) 2022 TechMahindra Ltd. * ================================================================================ * 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. @@ -27,14 +29,13 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post -import org.modelmapper.ModelMapper -import org.onap.cps.api.CpsQueryService +import org.mapstruct.factory.Mappers import org.onap.cps.api.CpsAdminService -import org.onap.cps.api.CpsDataService import org.onap.cps.api.CpsModuleService -import org.onap.cps.spi.exceptions.DataspaceAlreadyDefinedException +import org.onap.cps.spi.exceptions.AlreadyDefinedException import org.onap.cps.spi.exceptions.SchemaSetInUseException import org.onap.cps.spi.model.Anchor +import org.onap.cps.spi.model.Dataspace import org.onap.cps.spi.model.SchemaSet import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired @@ -47,9 +48,8 @@ import org.springframework.test.web.servlet.MockMvc import org.springframework.util.LinkedMultiValueMap import org.springframework.util.MultiValueMap import spock.lang.Specification -import spock.lang.Unroll -@WebMvcTest +@WebMvcTest(AdminRestController) class AdminRestControllerSpec extends Specification { @SpringBean @@ -59,13 +59,7 @@ class AdminRestControllerSpec extends Specification { CpsAdminService mockCpsAdminService = Mock() @SpringBean - CpsDataService mockCpsDataService = Mock() - - @SpringBean - CpsQueryService mockCpsQueryService = Mock() - - @SpringBean - ModelMapper modelMapper = Mock() + CpsRestInputMapper cpsRestInputMapper = Mappers.getMapper(CpsRestInputMapper) @Autowired MockMvc mvc @@ -74,77 +68,149 @@ class AdminRestControllerSpec extends Specification { def basePath def dataspaceName = 'my_dataspace' - def anchor = new Anchor(name: 'my_anchor') - def anchorList = [anchor] def anchorName = 'my_anchor' def schemaSetName = 'my_schema_set' + def anchor = new Anchor(name: anchorName, dataspaceName: dataspaceName, schemaSetName: schemaSetName) + def dataspace = new Dataspace(name: dataspaceName) - def 'Create new dataspace.'() { - given: 'an endpoint' - def createDataspaceEndpoint = "$basePath/v1/dataspaces"; + def 'Create new dataspace with #scenario.'() { when: 'post is invoked' - def response = mvc.perform( - post(createDataspaceEndpoint).param('dataspace-name', dataspaceName)).andReturn().response + def response = + mvc.perform( + post("/cps/api/${apiVersion}/dataspaces") + .param('dataspace-name', dataspaceName)) + .andReturn().response then: 'service method is invoked with expected parameters' 1 * mockCpsAdminService.createDataspace(dataspaceName) and: 'dataspace is create successfully' response.status == HttpStatus.CREATED.value() - } - + assert response.getContentAsString() == expectedResponseBody + where: 'following cases are tested' + scenario | apiVersion || expectedResponseBody + 'V1 API' | 'v1' || 'my_dataspace' + 'V2 API' | 'v2' || '' + } def 'Create dataspace over existing with same name.'() { given: 'an endpoint' - def createDataspaceEndpoint = "$basePath/v1/dataspaces"; + def createDataspaceEndpoint = "$basePath/v1/dataspaces" and: 'the service method throws an exception indicating the dataspace is already defined' - def thrownException = new DataspaceAlreadyDefinedException("", new RuntimeException()) + def thrownException = new AlreadyDefinedException(dataspaceName, new RuntimeException()) mockCpsAdminService.createDataspace(dataspaceName) >> { throw thrownException } when: 'post is invoked' - def response = mvc.perform(post(createDataspaceEndpoint).param('dataspace-name', dataspaceName)).andReturn().response + def response = + mvc.perform( + post(createDataspaceEndpoint) + .param('dataspace-name', dataspaceName)) + .andReturn().response then: 'dataspace creation fails' - response.status == HttpStatus.BAD_REQUEST.value() + response.status == HttpStatus.CONFLICT.value() + } + + def 'Get a dataspace.'() { + given: 'service method returns a dataspace' + mockCpsAdminService.getDataspace(dataspaceName) >> dataspace + and: 'an endpoint' + def getDataspaceEndpoint = "$basePath/v1/admin/dataspaces/$dataspaceName" + when: 'get dataspace API is invoked' + def response = mvc.perform(get(getDataspaceEndpoint)).andReturn().response + then: 'the correct dataspace is returned' + response.status == HttpStatus.OK.value() + response.getContentAsString().contains(dataspaceName) } - def 'Create schema set from yang file.'() { + def 'Get all dataspaces.'() { + given: 'service method returns all dataspace' + mockCpsAdminService.getAllDataspaces() >> [dataspace, new Dataspace(name: "dataspace-test2")] + and: 'an endpoint' + def getAllDataspaceEndpoint = "$basePath/v1/admin/dataspaces" + when: 'get all dataspace API is invoked' + def response = mvc.perform(get(getAllDataspaceEndpoint)).andReturn().response + then: 'the correct dataspace is returned' + response.status == HttpStatus.OK.value() + response.getContentAsString().contains(dataspaceName) + response.getContentAsString().contains("dataspace-test2") + } + + def 'Create schema set from yang file with #scenario.'() { def yangResourceMapCapture given: 'single yang file' def multipartFile = createMultipartFile("filename.yang", "content") - and: 'an endpoint' - def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets" when: 'file uploaded with schema set create request' - def response = mvc.perform(multipart(schemaSetEndpoint) - .file(multipartFile).param('schema-set-name', schemaSetName)).andReturn().response + def response = + mvc.perform( + multipart("/cps/api/${apiVersion}/dataspaces/my_dataspace/schema-sets") + .file(multipartFile) + .param('schema-set-name', schemaSetName)) + .andReturn().response then: 'associated service method is invoked with expected parameters' 1 * mockCpsModuleService.createSchemaSet(dataspaceName, schemaSetName, _) >> { args -> yangResourceMapCapture = args[2] } yangResourceMapCapture['filename.yang'] == 'content' and: 'response code indicates success' - response.status == HttpStatus.CREATED.value() + assert response.status == HttpStatus.CREATED.value() + assert response.getContentAsString() == expectedResponseBody + where: 'following cases are tested' + scenario | apiVersion || expectedResponseBody + 'V1 API' | 'v1' || 'my_schema_set' + 'V2 API' | 'v2' || '' } - def 'Create schema set from zip archive.'() { + def 'Create schema set from zip archive with #scenario.'() { def yangResourceMapCapture given: 'zip archive with multiple .yang files inside' def multipartFile = createZipMultipartFileFromResource("/yang-files-set.zip") - and: 'an endpoint' - def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets" when: 'file uploaded with schema set create request' - def response = mvc.perform(multipart(schemaSetEndpoint) - .file(multipartFile).param('schema-set-name', schemaSetName)).andReturn().response + def response = + mvc.perform( + multipart("/cps/api/${apiVersion}/dataspaces/my_dataspace/schema-sets") + .file(multipartFile) + .param('schema-set-name', schemaSetName)) + .andReturn().response then: 'associated service method is invoked with expected parameters' 1 * mockCpsModuleService.createSchemaSet(dataspaceName, schemaSetName, _) >> { args -> yangResourceMapCapture = args[2] } yangResourceMapCapture['assembly.yang'] == "fake assembly content 1\n" yangResourceMapCapture['component.yang'] == "fake component content 1\n" and: 'response code indicates success' - response.status == HttpStatus.CREATED.value() + assert response.status == HttpStatus.CREATED.value() + assert response.getContentAsString() == expectedResponseBody + where: 'following cases are tested' + scenario | apiVersion || expectedResponseBody + 'V1 API' | 'v1' || 'my_schema_set' + 'V2 API' | 'v2' || '' + } + + def 'Create a schema set from a yang file that is greater than 1MB #scenario.'() { + given: 'a yang file greater than 1MB' + def multipartFile = createMultipartFileFromResource("/model-over-1mb.yang") + when: 'a file is uploaded to the create schema set endpoint' + def response = + mvc.perform( + multipart("/cps/api/${apiVersion}/dataspaces/my_dataspace/schema-sets") + .file(multipartFile) + .param('schema-set-name', schemaSetName)) + .andReturn().response + then: 'the associated service method is invoked' + 1 * mockCpsModuleService.createSchemaSet(dataspaceName, schemaSetName, _) + and: 'the response code indicates success' + assert response.status == HttpStatus.CREATED.value() + assert response.getContentAsString() == expectedResponseBody + where: 'following cases are tested' + scenario | apiVersion || expectedResponseBody + 'V1 API' | 'v1' || 'my_schema_set' + 'V2 API' | 'v2' || '' } - @Unroll def 'Create schema set from zip archive having #caseDescriptor.'() { given: 'an endpoint' def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets" when: 'zip archive having #caseDescriptor is uploaded with create schema set request' - def response = mvc.perform(multipart(schemaSetEndpoint) - .file(multipartFile).param('schema-set-name', schemaSetName)).andReturn().response + def response = + mvc.perform( + multipart(schemaSetEndpoint) + .file(multipartFile) + .param('schema-set-name', schemaSetName)) + .andReturn().response then: 'create schema set rejected' response.status == HttpStatus.BAD_REQUEST.value() where: 'following cases are tested' @@ -159,20 +225,27 @@ class AdminRestControllerSpec extends Specification { and: 'an endpoint' def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets" when: 'file uploaded with schema set create request' - def response = mvc.perform(multipart(schemaSetEndpoint) - .file(multipartFile).param('schema-set-name', schemaSetName)).andReturn().response + def response = + mvc.perform( + multipart(schemaSetEndpoint) + .file(multipartFile) + .param('schema-set-name', schemaSetName)) + .andReturn().response then: 'create schema set rejected' response.status == HttpStatus.BAD_REQUEST.value() } - @Unroll def 'Create schema set from #fileType file with IOException occurrence on processing.'() { given: 'an endpoint' def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets" when: 'file uploaded with schema set create request' def multipartFile = createMultipartFileForIOException(fileType) - def response = mvc.perform(multipart(schemaSetEndpoint) - .file(multipartFile).param('schema-set-name', schemaSetName)).andReturn().response + def response = + mvc.perform( + multipart(schemaSetEndpoint) + .file(multipartFile) + .param('schema-set-name', schemaSetName)) + .andReturn().response then: 'the error response returned indicating internal server error occurrence' response.status == HttpStatus.INTERNAL_SERVER_ERROR.value() where: 'following file types are used' @@ -216,25 +289,46 @@ class AdminRestControllerSpec extends Specification { response.getContentAsString().contains(schemaSetName) } - def 'Create Anchor.'() { + def 'Get all schema sets for a given dataspace name.'() { + given: 'service method returns all schema sets for a dataspace' + mockCpsModuleService.getSchemaSets(dataspaceName) >> + [new SchemaSet(name: schemaSetName, dataspaceName: dataspaceName), + new SchemaSet(name: "test-schemaset", dataspaceName: dataspaceName)] + and: 'an endpoint' + def schemaSetEndpoint = "$basePath/v1/dataspaces/$dataspaceName/schema-sets" + when: 'get schema sets API is invoked' + def response = mvc.perform(get(schemaSetEndpoint)).andReturn().response + then: 'the correct schema sets is returned' + assert response.status == HttpStatus.OK.value() + assert response.getContentAsString() == '[{"dataspaceName":"my_dataspace","moduleReferences":[],"name":' + + '"my_schema_set"},{"dataspaceName":"my_dataspace","moduleReferences":[],"name":"test-schemaset"}]' + } + + def 'Create Anchor with #scenario.'() { given: 'request parameters' def requestParams = new LinkedMultiValueMap<>() requestParams.add('schema-set-name', schemaSetName) requestParams.add('anchor-name', anchorName) - and: 'an endpoint' - def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors" when: 'post is invoked' - def response = mvc.perform(post(anchorEndpoint).contentType(MediaType.APPLICATION_JSON) - .params(requestParams as MultiValueMap)).andReturn().response + def response = + mvc.perform( + post("/cps/api/${apiVersion}/dataspaces/my_dataspace/anchors") + .contentType(MediaType.APPLICATION_JSON) + .params(requestParams as MultiValueMap)) + .andReturn().response then: 'anchor is created successfully' 1 * mockCpsAdminService.createAnchor(dataspaceName, schemaSetName, anchorName) - response.status == HttpStatus.CREATED.value() - response.getContentAsString().contains(anchorName) + assert response.status == HttpStatus.CREATED.value() + assert response.getContentAsString() == expectedResponseBody + where: 'following cases are tested' + scenario | apiVersion || expectedResponseBody + 'V1 API' | 'v1' || 'my_anchor' + 'V2 API' | 'v2' || '' } def 'Get existing anchor.'() { given: 'service method returns a list of anchors' - mockCpsAdminService.getAnchors(dataspaceName) >> anchorList + mockCpsAdminService.getAnchors(dataspaceName) >> [anchor] and: 'an endpoint' def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors" when: 'get all anchors API is invoked' @@ -246,12 +340,12 @@ class AdminRestControllerSpec extends Specification { def 'Get existing anchor by dataspace and anchor name.'() { given: 'service method returns an anchor' - mockCpsAdminService.getAnchor(dataspaceName,anchorName) >> new Anchor(name: anchorName, dataspaceName: dataspaceName, schemaSetName:schemaSetName) + mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> + new Anchor(name: anchorName, dataspaceName: dataspaceName, schemaSetName: schemaSetName) and: 'an endpoint' def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors/$anchorName" when: 'get anchor API is invoked' - def response = mvc.perform(get(anchorEndpoint)) - .andReturn().response + def response = mvc.perform(get(anchorEndpoint)).andReturn().response def responseContent = response.getContentAsString() then: 'the correct anchor is returned' response.status == HttpStatus.OK.value() @@ -260,6 +354,30 @@ class AdminRestControllerSpec extends Specification { responseContent.contains(schemaSetName) } + def 'Delete anchor.'() { + given: 'an endpoint' + def anchorEndpoint = "$basePath/v1/dataspaces/$dataspaceName/anchors/$anchorName" + when: 'delete method is invoked on anchor endpoint' + def response = mvc.perform(delete(anchorEndpoint)).andReturn().response + then: 'associated service method is invoked with expected parameters' + 1 * mockCpsAdminService.deleteAnchor(dataspaceName, anchorName) + and: 'response code indicates success' + response.status == HttpStatus.NO_CONTENT.value() + } + + def 'Delete dataspace.'() { + given: 'an endpoint' + def dataspaceEndpoint = "$basePath/v1/dataspaces" + when: 'delete dataspace endpoint is invoked' + def response = mvc.perform(delete(dataspaceEndpoint) + .param('dataspace-name', dataspaceName)) + .andReturn().response + then: 'associated service method is invoked with expected parameter' + 1 * mockCpsAdminService.deleteDataspace(dataspaceName) + and: 'response code indicates success' + response.status == HttpStatus.NO_CONTENT.value() + } + def createMultipartFile(filename, content) { return new MockMultipartFile("file", filename, "text/plain", content.getBytes()) } @@ -269,6 +387,11 @@ class AdminRestControllerSpec extends Specification { getClass().getResource(resourcePath).getBytes()) } + def createMultipartFileFromResource(resourcePath) { + return new MockMultipartFile("file", "test.yang", "application/text", + getClass().getResource(resourcePath).getBytes()) + } + def createMultipartFileForIOException(extension) { def multipartFile = Mock(MockMultipartFile) multipartFile.getOriginalFilename() >> "TEST." + extension @@ -276,4 +399,5 @@ class AdminRestControllerSpec extends Specification { multipartFile.getInputStream() >> { throw new IOException() } return multipartFile } + }