From 612b697f8c28f3d7c6250e6c3235fc9bd50b8366 Mon Sep 17 00:00:00 2001 From: ToineSiebelink Date: Fri, 10 Sep 2021 11:45:17 +0100 Subject: [PATCH] Add test for missing code covereage - Add test for error scenarios and otehr mising tests - set up for SpringBean testing - some small typo fixes - fixed some SQ violations Issue-ID: CPS-656 Change-Id: If33f215c8ecaf090f27145005cc1aa7f0331d0f4 Signed-off-by: ToineSiebelink --- .../java/org/onap/cps/ncmp/api/impl/JsonUtils.java | 3 + .../api/impl/NetworkCmProxyDataServiceImpl.java | 41 ++++++----- .../ncmp/api/impl/config/NcmpConfiguration.java | 4 +- .../cps/ncmp/api/impl/exception/NcmpException.java | 12 --- .../onap/cps/ncmp/api/impl/JsonUtilsSpec.groovy | 7 ++ .../impl/NetworkCmProxyDataServiceImplSpec.groovy | 85 +++++++++++++++++----- .../ncmp/api/impl/client/DmiRestClientSpec.groovy | 26 +++---- .../api/impl/config/NcmpConfigurationSpec.groovy | 52 +++++++++++++ .../ncmp/api/models/PersistenceCmHandleSpec.groovy | 42 +++++++++++ .../cps/ncmp/api/models/moduleReferenceSpec.groovy | 19 +++++ .../src/test/resources/application.yml | 23 ++++++ ...CpsDataPersistenceServiceIntegrationSpec.groovy | 22 ++++-- .../spi/impl/CpsDataPersistenceServiceSpec.groovy | 14 ++++ 13 files changed, 277 insertions(+), 73 deletions(-) create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy create mode 100644 cps-ncmp-service/src/test/resources/application.yml diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/JsonUtils.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/JsonUtils.java index 9ce32e390..6768777e1 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/JsonUtils.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/JsonUtils.java @@ -26,6 +26,9 @@ public class JsonUtils { private static final String NEW_LINE = "\n"; private static final String QUOTE = "\""; + private JsonUtils() { + throw new IllegalStateException(); + } /** * Remove redundant beginning and end characters. diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java index 24203c0d7..a28b73c42 100755 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java @@ -76,6 +76,8 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private static final String NCMP_DMI_SERVICE_NAME = "dmi-service-name"; + private static final String REVISION = "revision"; + private CpsDataService cpsDataService; private ObjectMapper objectMapper; @@ -88,8 +90,6 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private CpsAdminService cpsAdminService; - public static final String NO_NAMESPACE = null; - /** * Constructor Injection for Dependencies. * @param dmiOperations DMI operation @@ -279,11 +279,11 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService private String getGenericRequestBody(final DataNode cmHandleDataNode) { final Collection cmHandlePropertiesList = cmHandleDataNode.getChildDataNodes(); final Map cmHandlePropertiesMap = getCmHandlePropertiesAsMap(cmHandlePropertiesList); - final var requetBodyObject = GenericRequestBody.builder() + final var requestBodyObject = GenericRequestBody.builder() .operation(GenericRequestBody.OperationEnum.READ) .cmHandleProperties(cmHandlePropertiesMap) .build(); - return prepareOperationBody(requetBodyObject); + return prepareOperationBody(requestBodyObject); } private void parseAndUpdateCmHandlesInDmiRegistration(final DmiPluginRegistration dmiPluginRegistration) { @@ -299,10 +299,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService cpsDataService.updateNodeLeavesAndExistingDescendantLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "/dmi-registry", cmHandlesJsonData, NO_TIMESTAMP); } catch (final JsonProcessingException e) { - log.error("Parsing error occurred while converting Object to JSON DMI Registry."); - throw new DataValidationException( - "Parsing error occurred while processing DMI Plugin Registration" + dmiPluginRegistration, e - .getMessage(), e); + handleJsonProcessingException(dmiPluginRegistration, e); } } @@ -317,17 +314,21 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService } final String cmHandleJsonData = objectMapper.writeValueAsString(persistenceCmHandlesList); - registerAndSyncNode(dmiPluginRegistration, persistenceCmHandlesList, cmHandleJsonData); + registerAndSyncNode(persistenceCmHandlesList, cmHandleJsonData); } catch (final JsonProcessingException e) { - log.error("Parsing error occurred while converting Object to JSON for DMI Registry."); - throw new DataValidationException( - "Parsing error occurred while processing DMI Plugin Registration" + dmiPluginRegistration, e - .getMessage(), e); + handleJsonProcessingException(dmiPluginRegistration, e); } } - private void registerAndSyncNode(final DmiPluginRegistration dmiPluginRegistration, - final PersistenceCmHandlesList persistenceCmHandlesList, + private static void handleJsonProcessingException(final DmiPluginRegistration dmiPluginRegistration, + final JsonProcessingException e) { + final String message = "Parsing error occurred while processing DMI Plugin Registration" + + dmiPluginRegistration; + log.error(message); + throw new DataValidationException(message, e.getMessage(), e); + } + + private void registerAndSyncNode(final PersistenceCmHandlesList persistenceCmHandlesList, final String cmHandleJsonData) { cpsDataService.saveListNodeData(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, "/dmi-registry", cmHandleJsonData, NO_TIMESTAMP); @@ -390,7 +391,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService cpsAdminService.createAnchor(NF_PROXY_DATASPACE_NAME, cmHandle.getId(), cmHandle.getId()); } - private JsonObject getRequestBodyAsJson(final List unknownModuleReferences) { + private static JsonObject getRequestBodyAsJson(final List unknownModuleReferences) { final JsonObject requestBodyAsJson = new JsonObject(); requestBodyAsJson.addProperty("operation", "read"); @@ -404,13 +405,13 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService return requestBodyAsJson; } - private JsonArray getModuleReferencesAsJson(final List unknownModuleReferences) { + private static JsonArray getModuleReferencesAsJson(final List unknownModuleReferences) { final JsonArray moduleReferences = new JsonArray(); for (final ModuleReference moduleReference : unknownModuleReferences) { final JsonObject moduleReferenceAsJson = new JsonObject(); moduleReferenceAsJson.addProperty("name", moduleReference.getModuleName()); - moduleReferenceAsJson.addProperty("revision", moduleReference.getRevision()); + moduleReferenceAsJson.addProperty(REVISION, moduleReference.getRevision()); moduleReferences.add(moduleReferenceAsJson); } return moduleReferences; @@ -444,7 +445,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService return yangResource; } - private List getModuleReferences(final ResponseEntity response) { + private static List getModuleReferences(final ResponseEntity response) { final List modulesFromDmiForCmHandle = new ArrayList<>(); final JsonObject convertedObject = new Gson().fromJson(response.getBody(), JsonObject.class); final JsonArray moduleReferencesAsJson = convertedObject.getAsJsonArray("schemas"); @@ -456,7 +457,7 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService return modulesFromDmiForCmHandle; } - private ModuleReference toModuleReference(final JsonObject moduleReferenceAsJson) { + private static ModuleReference toModuleReference(final JsonObject moduleReferenceAsJson) { final var moduleReference = new ModuleReference(); moduleReference.setModuleName(moduleReferenceAsJson.get("moduleName").getAsString()); moduleReference.setRevision(moduleReferenceAsJson.get("revision").getAsString()); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java index a834bfcd9..c4e82d329 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/NcmpConfiguration.java @@ -41,7 +41,7 @@ public class NcmpConfiguration { } @Bean - public RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder) { + public static RestTemplate restTemplate(final RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder.build(); } -} \ No newline at end of file +} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java index ff5346409..2c75b5d99 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/exception/NcmpException.java @@ -43,17 +43,5 @@ public class NcmpException extends RuntimeException { this.details = details; } - /** - * Constructor. - * - * @param message the error message - * @param details the error details - * @param cause the cause of the exception - */ - public NcmpException(final String message, final String details, final Throwable cause) { - super(message, cause); - this.details = details; - } - } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/JsonUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/JsonUtilsSpec.groovy index 2b3d99864..be27dfad5 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/JsonUtilsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/JsonUtilsSpec.groovy @@ -40,5 +40,12 @@ class JsonUtilsSpec extends Specification { 'a string in apostrophes' | "'abc'" || 'abc' 'a string inside any other tokens' | 'abcde' || 'bcd' } + + def 'Cannot use constructor.'() { + when: 'attempt to construct object' + new JsonUtils() + then: 'an exception is thrown' + thrown(IllegalStateException) + } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy index 3ebb4550c..8739355c8 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy @@ -36,6 +36,8 @@ import org.onap.cps.ncmp.api.models.DmiPluginRegistration import org.onap.cps.ncmp.api.models.PersistenceCmHandle import org.onap.cps.ncmp.utils.TestUtils import org.onap.cps.spi.FetchDescendantsOption +import org.onap.cps.spi.exceptions.DataNodeNotFoundException +import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.model.DataNode import org.onap.cps.spi.model.ModuleReference import org.springframework.http.HttpStatus @@ -56,9 +58,10 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def mockCpsModuleService = Mock(CpsModuleService) def mockCpsAdminService = Mock(CpsAdminService) def mockDmiProperties = Mock(NcmpConfiguration.DmiProperties) + def spyObjectMapper = Spy(ObjectMapper) def objectUnderTest = new NetworkCmProxyDataServiceImpl(mockDmiOperations, mockCpsModuleService, - mockCpsDataService, mockCpsQueryService, mockCpsAdminService, new ObjectMapper()) + mockCpsDataService, mockCpsQueryService, mockCpsAdminService, spyObjectMapper) def cmHandle = 'some handle' def noTimestamp = null @@ -154,12 +157,12 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'ncmp-dmi-registry', "/dmi-registry/cm-handles[@id='cmHandle001']", noTimestamp) where: - scenario | createdCmHandles | updatedCmHandles | removedCmHandles || expectedCallsToSaveNode | expectedCallsToUpdateNode | expectedCallsToDeleteListDataNode - 'create' | [persistenceCmHandle ] | [] | [] || 1 | 0 | 0 - 'update' | [] | [persistenceCmHandle ] | [] || 0 | 1 | 0 - 'delete' | [] | [] | cmHandlesArray || 0 | 0 | 1 - 'create, update and delete' | [persistenceCmHandle ] | [persistenceCmHandle ] | cmHandlesArray || 1 | 1 | 1 - + scenario | createdCmHandles | updatedCmHandles | removedCmHandles || expectedCallsToSaveNode | expectedCallsToUpdateNode | expectedCallsToDeleteListDataNode + 'create' | [persistenceCmHandle] | [] | [] || 1 | 0 | 0 + 'update' | [] | [persistenceCmHandle] | [] || 0 | 1 | 0 + 'delete' | [] | [] | cmHandlesArray || 0 | 0 | 1 + 'create, update and delete' | [persistenceCmHandle] | [persistenceCmHandle] | cmHandlesArray || 1 | 1 | 1 + 'no valid data' | null | null | null || 0 | 0 | 0 } def 'Register a DMI Plugin for the given cmHandle without additional properties.'() { @@ -169,7 +172,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { dmiPluginRegistration.dmiPlugin = 'my-server' persistenceCmHandle.cmHandleID = '123' persistenceCmHandle.cmHandleProperties = null - dmiPluginRegistration.createdCmHandles = [persistenceCmHandle ] + dmiPluginRegistration.createdCmHandles = [persistenceCmHandle] def expectedJsonData = '{"cm-handles":[{"id":"123","dmi-service-name":"my-server","additional-properties":[]}]}' when: 'registration is updated' objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) @@ -178,6 +181,37 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { '/dmi-registry', expectedJsonData, noTimestamp) } + def 'Register a DMI Plugin with JSON processing errors during #scenario.'() { + given: 'a registration without cmHandle properties ' + NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled() + def dmiPluginRegistration = new DmiPluginRegistration() + dmiPluginRegistration.createdCmHandles = createdCmHandles + dmiPluginRegistration.updatedCmHandles = updatedCmHandles + and: 'an JSON processing exception occurs' + spyObjectMapper.writeValueAsString(_) >> { throw (new JsonProcessingException('')) } + when: 'registration is updated' + objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) + then: 'a data validation exception is thrown' + thrown(DataValidationException) + where: + scenario | createdCmHandles | updatedCmHandles + 'create' | [persistenceCmHandle] | [] + 'update' | [] | [persistenceCmHandle] + } + + def 'Register a DMI Plugin with no data found during delete.'() { + given: 'a registration without cmHandle properties ' + NetworkCmProxyDataServiceImpl objectUnderTest = getObjectUnderTestWithModelSyncDisabled() + def dmiPluginRegistration = new DmiPluginRegistration() + dmiPluginRegistration.removedCmHandles = ['some cm handle'] + and: 'an JSON processing exception occurs' + mockCpsDataService.deleteListNodeData(*_) >> { throw (new DataNodeNotFoundException('','')) } + when: 'registration is updated' + objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration) + then: 'no exception is thrown' + noExceptionThrown() + } + def 'Get resource data for pass-through operational from dmi.'() { given: 'data node representing cmHandle and its properties' def cmHandleDataNode = getCmHandleDataNodeForTest() @@ -211,15 +245,16 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { and: 'objectMapper not able to parse object' def mockObjectMapper = Mock(ObjectMapper) objectUnderTest.objectMapper = mockObjectMapper - mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException("testException") } + mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException('testException') } when: 'get resource data is called' def response = objectUnderTest.getResourceDataOperationalForCmHandle('testCmHandle', 'testResourceId', 'testAcceptParam', 'testFieldQuery', 5) - then: 'exception is thrown' - thrown(NcmpException.class) + then: 'exception is thrown with the expected details' + def exceptionThrown = thrown(NcmpException.class) + exceptionThrown.details == 'testException' } def 'Get resource data for pass-through operational from dmi return NOK response.'() { @@ -244,7 +279,9 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'testFieldQuery', 5) then: 'exception is thrown' - thrown(NcmpException.class) + def exceptionThrown = thrown(NcmpException.class) + and: 'details contains the original response' + exceptionThrown.details.contains('NOK-json') } def 'Get resource data for pass-through running from dmi.'() { @@ -280,15 +317,16 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { and: 'objectMapper not able to parse object' def mockObjectMapper = Mock(ObjectMapper) objectUnderTest.objectMapper = mockObjectMapper - mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException("testException") } + mockObjectMapper.writeValueAsString(_) >> { throw new JsonProcessingException('testException') } when: 'get resource data is called' def response = objectUnderTest.getResourceDataPassThroughRunningForCmHandle('testCmHandle', 'testResourceId', 'testAcceptParam', 'testFieldQuery', 5) - then: 'exception is thrown' - thrown(NcmpException.class) + then: 'exception is thrown with the expected details' + def exceptionThrown = thrown(NcmpException.class) + exceptionThrown.details == 'testException' } def 'Get resource data for pass-through running from dmi return NOK response.'() { @@ -313,7 +351,9 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'testFieldQuery', 5) then: 'exception is thrown' - thrown(NcmpException.class) + def exceptionThrown = thrown(NcmpException.class) + and: 'details contains the original response' + exceptionThrown.details.contains('NOK-json') } def 'Write resource data for pass-through running from dmi using POST.'() { @@ -348,7 +388,9 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'testResourceId', '{some-json}', 'application/json') then: 'exception is thrown' - thrown(NcmpException.class) + def exceptionThrown = thrown(NcmpException.class) + and: 'details contains (not found) error code: 404' + exceptionThrown.details.contains('404') } def 'Sync model for a (new) cm handle with #scenario'() { @@ -373,6 +415,13 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { 'no unknown module' | '[]' || [:] } + def 'Getting Yang Resources.'() { + when: 'yang resources is called' + objectUnderTest.getYangResourcesModuleReferences('some cm handle') + then: 'CPS module services is invoked for the correct dataspace and cm handle' + 1 * mockCpsModuleService.getYangResourcesModuleReferences('NFP-Operational','some cm handle') + } + def getModulesForCmHandle() { def jsonData = TestUtils.getResourceFileContent('cmHandleModules.json') mockDmiProperties.getAuthUsername() >> 'someUser' @@ -384,7 +433,7 @@ class NetworkCmProxyDataServiceImplSpec extends Specification { def getObjectUnderTestWithModelSyncDisabled() { def objectUnderTest = Spy(new NetworkCmProxyDataServiceImpl(mockDmiOperations, mockCpsModuleService, - mockCpsDataService, mockCpsQueryService, mockCpsAdminService, new ObjectMapper())) + mockCpsDataService, mockCpsQueryService, mockCpsAdminService, spyObjectMapper)) objectUnderTest.createAnchorAndSyncModel(_) >> null return objectUnderTest } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy index 809c48a61..bf6179ba1 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/client/DmiRestClientSpec.groovy @@ -21,24 +21,30 @@ package org.onap.cps.ncmp.api.impl.client import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration +import org.spockframework.spring.SpringBean +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest import org.springframework.http.HttpEntity import org.springframework.http.HttpHeaders +import org.springframework.http.HttpMethod import org.springframework.http.ResponseEntity +import org.springframework.test.context.ContextConfiguration import org.springframework.web.client.RestTemplate import spock.lang.Specification -import org.springframework.http.HttpMethod +@SpringBootTest +@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties, DmiRestClient]) class DmiRestClientSpec extends Specification { - def mockDmiProperties = Mock(NcmpConfiguration.DmiProperties) - def mockRestTemplate = Mock(RestTemplate) - def objectUnderTest = new DmiRestClient(mockRestTemplate, mockDmiProperties) + @SpringBean + RestTemplate mockRestTemplate = Mock(RestTemplate) + + @Autowired + DmiRestClient objectUnderTest def 'DMI PUT operation.'() { given: 'a PUT url' def getResourceDataUrl = 'http://some-uri/getResourceDataUrl' - and: 'dmi properties' - setupTestConfigurationData() and: 'the rest template returns a valid response entity' def mockResponseEntity = Mock(ResponseEntity) mockRestTemplate.exchange(getResourceDataUrl, HttpMethod.PUT, _ as HttpEntity, Object.class) >> mockResponseEntity @@ -51,8 +57,6 @@ class DmiRestClientSpec extends Specification { def 'DMI POST operation.'() { given: 'a POST url' def getResourceDataUrl = 'http://some-uri/createResourceDataUrl' - and: 'dmi properties' - setupTestConfigurationData() and: 'the rest template returns a valid response entity' def mockResponseEntity = Mock(ResponseEntity) mockRestTemplate.postForEntity(getResourceDataUrl, _ as HttpEntity, String.class) >> mockResponseEntity @@ -62,8 +66,4 @@ class DmiRestClientSpec extends Specification { result == mockResponseEntity } - def setupTestConfigurationData() { - mockDmiProperties.authUsername >> 'some-username' - mockDmiProperties.authPassword >> 'some-password' - } -} \ No newline at end of file +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy new file mode 100644 index 000000000..dd4c1375b --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/NcmpConfigurationSpec.groovy @@ -0,0 +1,52 @@ +/* + * ============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.api.impl.config + +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.web.client.RestTemplateBuilder +import org.springframework.test.context.ContextConfiguration +import org.springframework.web.client.RestTemplate +import spock.lang.Specification + +@SpringBootTest +@ContextConfiguration(classes = [NcmpConfiguration.DmiProperties]) +class NcmpConfigurationSpec extends Specification{ + + @Autowired + NcmpConfiguration.DmiProperties dmiProperties + + def 'DMI Properties.'() { + expect: 'properties are set to values in test configuration yaml file' + dmiProperties.authUsername == 'some-user' + dmiProperties.authPassword == 'some-password' + } + + def 'Rest Template creation.'() { + given: 'a rest template builder' + def mockRestTemplateBuilder = Mock(RestTemplateBuilder) + def expectedRestTemplate = Mock(RestTemplate) + mockRestTemplateBuilder.build() >> expectedRestTemplate + when: 'a rest template is created' + def result = NcmpConfiguration.restTemplate(mockRestTemplateBuilder) + then: 'the rest template from the builder is returned' + assert result == expectedRestTemplate + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy new file mode 100644 index 000000000..bfed795f7 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/PersistenceCmHandleSpec.groovy @@ -0,0 +1,42 @@ +/* + * ============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.api.models + +import spock.lang.Specification + +class PersistenceCmHandleSpec extends Specification { + + def objectUnderTest = new PersistenceCmHandle() + + def 'Setting and getting additional properties.'() { + given: 'a map of one property is added' + objectUnderTest.setAdditionalProperties([myProperty: 'some value']) + when: 'the additional properties are retrieved' + def result = objectUnderTest.getAdditionalProperties() + then: 'the result has the right size' + assert result.size() == 1 + and: 'the property in the result has the correct name and value' + def actualAdditionalProperty = result.get(0) + def expectedAdditionalProperty = new PersistenceCmHandle.AdditionalProperty('myProperty','some value') + assert actualAdditionalProperty.name == expectedAdditionalProperty.name + assert actualAdditionalProperty.value == expectedAdditionalProperty.value + } + +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/moduleReferenceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/moduleReferenceSpec.groovy index 9f161a9e5..444a25804 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/moduleReferenceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/moduleReferenceSpec.groovy @@ -1,3 +1,22 @@ +/* + * ============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.api.models import org.onap.cps.spi.model.ExtendedModuleReference diff --git a/cps-ncmp-service/src/test/resources/application.yml b/cps-ncmp-service/src/test/resources/application.yml new file mode 100644 index 000000000..71ac2c9a0 --- /dev/null +++ b/cps-ncmp-service/src/test/resources/application.yml @@ -0,0 +1,23 @@ +# ============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========================================================= + +dmi: + auth: + username: some-user + password: some-password + diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy index 8217a4fb0..e2316e863 100755 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceIntegrationSpec.groovy @@ -21,11 +21,6 @@ */ package org.onap.cps.spi.impl -import org.onap.cps.spi.exceptions.DataValidationException - -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS - import com.google.common.collect.ImmutableSet import com.google.gson.Gson import com.google.gson.GsonBuilder @@ -42,6 +37,9 @@ import org.springframework.test.context.jdbc.Sql import javax.validation.ConstraintViolationException +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS + class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase { @Autowired @@ -155,17 +153,25 @@ class CpsDataPersistenceServiceIntegrationSpec extends CpsPersistenceSpecBase { } @Sql([CLEAR_DATA, SET_DATA]) - def 'Add list-node fragment with multiple elements.'() { - given: 'list node data fragment as a collection of data nodes' + def 'Add list-node fragment with multiple elements including an element with a child datanode.'() { + given: 'two new data nodes for an existing list' def listNodeXpaths = ['/parent-201/child-204[@key="B"]', '/parent-201/child-204[@key="C"]'] def listNodeCollection = buildDataNodeCollection(listNodeXpaths) - when: 'list-node elements added to existing parent node' + and: 'a child node for one of the new data nodes' + def childDataNode = buildDataNode('/parent-201/child-204[@key="C"]/grand-child-204[@key2="Z"]', [leave:'value'], []) + listNodeCollection.iterator().next().childDataNodes = [childDataNode] + when: 'the data nodes (list elements) are added to existing parent node' objectUnderTest.addListDataNodes(DATASPACE_NAME, ANCHOR_NAME3, '/parent-201', listNodeCollection) then: 'new entries successfully persisted, parent node now contains 5 children (2 new + 3 existing before)' def parentFragment = fragmentRepository.getById(LIST_DATA_NODE_PARENT201_FRAGMENT_ID) def allChildXpaths = parentFragment.getChildFragments().collect { it.getXpath() } assert allChildXpaths.size() == 5 assert allChildXpaths.containsAll(listNodeXpaths) + and: 'the child node of the new list entry is also present' + def dataspaceEntity = dataspaceRepository.getByName(DATASPACE_NAME) + def anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, ANCHOR_NAME3) + def listElementChild = fragmentRepository.findByDataspaceAndAnchorAndXpath(dataspaceEntity, anchorEntity, childDataNode.xpath) + assert listElementChild.isPresent() } @Sql([CLEAR_DATA, SET_DATA]) diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy index 9fcd550bd..162a56682 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy @@ -22,6 +22,7 @@ import org.hibernate.StaleStateException import org.onap.cps.spi.FetchDescendantsOption import org.onap.cps.spi.entities.FragmentEntity import org.onap.cps.spi.exceptions.ConcurrencyException +import org.onap.cps.spi.exceptions.DataValidationException import org.onap.cps.spi.model.DataNodeBuilder import org.onap.cps.spi.repository.AnchorRepository import org.onap.cps.spi.repository.DataspaceRepository @@ -95,4 +96,17 @@ class CpsDataPersistenceServiceSpec extends Specification { 'text and numbers' | '"String = \'1234\'"' || "String = '1234'" | String 'number as String' | '"12345"' || '12345' | String } + + def 'Retrieving a data node with invalid JSON'() { + given: 'a fragment with invalid JSON' + mockFragmentRepository.getByDataspaceAndAnchorAndXpath(_, _, _) >> { + new FragmentEntity(childFragments: Collections.emptySet(), attributes: '{invalid json') + } + when: 'getting the data node represented by this fragment' + def dataNode = objectUnderTest.getDataNode('my-dataspace', 'my-anchor', + 'parent-01', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + then: 'a data validation exception is thrown' + thrown(DataValidationException) + } + } -- 2.16.6