CPS Validator Changes
Changed CPS Validator from static to non-static
Moved CPSValidator implementation to rest interface layer to prevent duplicated usage
Created CPSValidator interface in persistence layer
Removed unnecessary tests
Refactored misplaced tests
Copyright fixes
Copyright Check Script output formatting fix
Issue-ID: CPS-1228
Signed-off-by: lukegleeson <luke.gleeson@est.tech>
Change-Id: I4c99a51870e7d3b8e416bc1f909aeed5dc3baa42
diff --git a/checkstyle/src/main/CopyrightCheck.py b/checkstyle/src/main/CopyrightCheck.py
index 8f1dbff..ff3d402 100644
--- a/checkstyle/src/main/CopyrightCheck.py
+++ b/checkstyle/src/main/CopyrightCheck.py
@@ -221,7 +221,7 @@
for copyrightInFileKey, templateLine in zip(copyrightInFile, templateCopyright):
if copyrightInFile[copyrightInFileKey] != templateLine:
issueCounter += 1
- errorWithComparison += filePath + ' | line ' + '{:2}'.format(copyrightInFileKey) + ' read \t ' + repr(copyrightInFile[copyrightInFileKey]) + '\n'
+ errorWithComparison += filePath + ' | line ' + '{:2}'.format(copyrightInFileKey) + ' read \t ' + repr(copyrightInFile[copyrightInFileKey]) + '\n'
errorWithComparison += filePath + ' | line ' + '{:2}'.format(copyrightInFileKey) + ' expected ' + repr(templateLine) + '\n'
if errorWithComparison != '':
print(errorWithComparison.rstrip('\n'))
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 0983889..27c3646 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
@@ -67,7 +67,6 @@
import org.onap.cps.spi.model.CmHandleQueryServiceParameters;
import org.onap.cps.spi.model.ModuleDefinition;
import org.onap.cps.spi.model.ModuleReference;
-import org.onap.cps.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
@@ -148,20 +147,17 @@
final OperationEnum operation,
final String requestData,
final String dataType) {
- CpsValidator.validateNameCharacters(cmHandleId);
return dmiDataOperations.writeResourceDataPassThroughRunningFromDmi(cmHandleId, resourceIdentifier, operation,
requestData, dataType);
}
@Override
public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
return inventoryPersistence.getYangResourcesModuleReferences(cmHandleId);
}
@Override
public Collection<ModuleDefinition> getModuleDefinitionsByCmHandleId(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
return inventoryPersistence.getModuleDefinitionsByCmHandleId(cmHandleId);
}
@@ -206,7 +202,6 @@
*/
@Override
public void setDataSyncEnabled(final String cmHandleId, final boolean dataSyncEnabled) {
- CpsValidator.validateNameCharacters(cmHandleId);
final CompositeState compositeState = inventoryPersistence
.getCmHandleState(cmHandleId);
if (compositeState.getDataSyncEnabled().equals(dataSyncEnabled)) {
@@ -250,7 +245,6 @@
*/
@Override
public NcmpServiceCmHandle getNcmpServiceCmHandle(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
return YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(
inventoryPersistence.getYangModelCmHandle(cmHandleId));
}
@@ -263,7 +257,6 @@
*/
@Override
public Map<String, String> getCmHandlePublicProperties(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
final YangModelCmHandle yangModelCmHandle =
inventoryPersistence.getYangModelCmHandle(cmHandleId);
final List<YangModelCmHandle.Property> yangModelPublicProperties = yangModelCmHandle.getPublicProperties();
@@ -280,7 +273,6 @@
*/
@Override
public CompositeState getCmHandleCompositeState(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
return inventoryPersistence.getYangModelCmHandle(cmHandleId).getCompositeState();
}
@@ -320,7 +312,6 @@
new ArrayList<>(tobeRemovedCmHandles.size());
for (final String cmHandleId : tobeRemovedCmHandles) {
try {
- CpsValidator.validateNameCharacters(cmHandleId);
final YangModelCmHandle yangModelCmHandle = inventoryPersistence.getYangModelCmHandle(cmHandleId);
lcmEventsCmHandleStateHandler.updateCmHandleState(yangModelCmHandle,
CmHandleState.DELETING);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
index d9aeaf2..f39c2f9 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java
@@ -43,7 +43,6 @@
import org.onap.cps.spi.exceptions.DataValidationException;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.DataNodeBuilder;
-import org.onap.cps.utils.CpsValidator;
import org.springframework.stereotype.Service;
@Slf4j
@@ -67,7 +66,6 @@
for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
final String cmHandleId = ncmpServiceCmHandle.getCmHandleId();
try {
- CpsValidator.validateNameCharacters(cmHandleId);
final DataNode existingCmHandleDataNode = inventoryPersistence.getCmHandleDataNode(cmHandleId);
processUpdates(existingCmHandleDataNode, ncmpServiceCmHandle);
cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createSuccessResponse(cmHandleId));
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
index d46d634..83faa00 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java
@@ -16,7 +16,7 @@
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
+ * ============LICENSE_END=========================================================
*/
package org.onap.cps.ncmp.api.impl.operations;
@@ -33,7 +33,6 @@
import org.onap.cps.ncmp.api.inventory.CmHandleState;
import org.onap.cps.ncmp.api.inventory.InventoryPersistence;
import org.onap.cps.spi.exceptions.CpsException;
-import org.onap.cps.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
@@ -131,7 +130,6 @@
}
private YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
return inventoryPersistence.getYangModelCmHandle(cmHandleId);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
index b679107..5f4a654 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java
@@ -15,7 +15,7 @@
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
+ * ============LICENSE_END=========================================================
*/
package org.onap.cps.ncmp.api.impl.utils;
@@ -30,7 +30,7 @@
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
import org.onap.cps.ncmp.api.impl.operations.DmiOperations;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
-import org.onap.cps.utils.CpsValidator;
+import org.onap.cps.spi.utils.CpsValidator;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -41,6 +41,7 @@
public class DmiServiceUrlBuilder {
private final NcmpConfiguration.DmiProperties dmiProperties;
+ private final CpsValidator cpsValidator;
/**
* This method creates the dmi service url.
@@ -84,7 +85,7 @@
public Map<String, Object> populateUriVariables(final YangModelCmHandle yangModelCmHandle,
final String cmHandleId,
final DmiOperations.DataStoreEnum dataStore) {
- CpsValidator.validateNameCharacters(cmHandleId);
+ cpsValidator.validateNameCharacters(cmHandleId);
final Map<String, Object> uriVariables = new HashMap<>();
final String dmiBasePath = dmiProperties.getDmiBasePath();
uriVariables.put("dmiServiceName",
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
index f842ddb..aabc52c 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java
@@ -37,7 +37,6 @@
import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
import org.onap.cps.ncmp.api.inventory.CompositeState;
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
-import org.onap.cps.utils.CpsValidator;
/**
* Cm Handle which follows the Yang resource dmi registry model when persisting data to DMI or the DB.
@@ -104,7 +103,6 @@
final String dmiDataServiceName,
final String dmiModelServiceName,
final NcmpServiceCmHandle ncmpServiceCmHandle) {
- CpsValidator.validateNameCharacters(ncmpServiceCmHandle.getCmHandleId());
final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle();
yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId());
yangModelCmHandle.setDmiServiceName(dmiServiceName);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
index eed47ed..adba198 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
@@ -46,7 +46,7 @@
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.ModuleDefinition;
import org.onap.cps.spi.model.ModuleReference;
-import org.onap.cps.utils.CpsValidator;
+import org.onap.cps.spi.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Component;
@@ -73,11 +73,14 @@
private final CpsAdminPersistenceService cpsAdminPersistenceService;
+ private final CpsValidator cpsValidator;
+
@Override
public CompositeState getCmHandleState(final String cmHandleId) {
final DataNode stateAsDataNode = cpsDataService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
- String.format(CM_HANDLE_XPATH_TEMPLATE, cmHandleId) + "/state",
- FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
+ String.format(CM_HANDLE_XPATH_TEMPLATE, cmHandleId) + "/state",
+ FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS);
+ cpsValidator.validateNameCharacters(cmHandleId);
return new CompositeStateBuilder().fromDataNode(stateAsDataNode).build();
}
@@ -102,7 +105,7 @@
@Override
public YangModelCmHandle getYangModelCmHandle(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
+ cpsValidator.validateNameCharacters(cmHandleId);
return YangDataConverter.convertCmHandleToYangModel(getCmHandleDataNode(cmHandleId), cmHandleId);
}
@@ -113,7 +116,7 @@
@Override
public Collection<ModuleReference> getYangResourcesModuleReferences(final String cmHandleId) {
- CpsValidator.validateNameCharacters(cmHandleId);
+ cpsValidator.validateNameCharacters(cmHandleId);
return cpsModuleService.getYangResourcesModuleReferences(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, cmHandleId);
}
@@ -143,7 +146,7 @@
@Override
public void deleteSchemaSetWithCascade(final String schemaSetName) {
try {
- CpsValidator.validateNameCharacters(schemaSetName);
+ cpsValidator.validateNameCharacters(schemaSetName);
cpsModuleService.deleteSchemaSet(NFP_OPERATIONAL_DATASTORE_DATASPACE_NAME, schemaSetName,
CASCADE_DELETE_ALLOWED);
} catch (final SchemaSetNotFoundException schemaSetNotFoundException) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
index 3a0f3c7..e6c79f8 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy
@@ -1,5 +1,5 @@
/*
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* Copyright (C) 2021-2022 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
@@ -222,7 +222,6 @@
where:
scenario | cmHandleId | exception || expectedError | expectedErrorText
'cm-handle already exist' | 'cmhandle' | new AlreadyDefinedExceptionBatch(["path[@id='${cmHandleId}']".toString()]) || CM_HANDLE_ALREADY_EXIST | 'cm-handle already exists'
- 'cm-handle has invalid name' | 'cm handle with space' | new DataValidationException("", "") || CM_HANDLE_INVALID_ID | 'cm-handle has an invalid character(s) in id'
'unknown exception while registering cm-handle' | 'cmhandle' | new RuntimeException('Failed') || UNKNOWN_ERROR | 'Failed'
}
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 91eb218..58ca06b 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
@@ -33,10 +33,12 @@
import org.onap.cps.ncmp.api.inventory.LockReasonCategory
import org.onap.cps.ncmp.api.inventory.DataStoreSyncState
import org.onap.cps.ncmp.api.models.CmHandleQueryApiParameters
+import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse
import org.onap.cps.ncmp.api.models.ConditionApiProperties
import org.onap.cps.ncmp.api.models.DmiPluginRegistration
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.spi.exceptions.CpsException
+import org.onap.cps.spi.exceptions.DataNodeNotFoundException
import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.model.CmHandleQueryServiceParameters
import spock.lang.Shared
@@ -55,6 +57,10 @@
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.CREATE
import static org.onap.cps.ncmp.api.impl.operations.DmiRequestBody.OperationEnum.UPDATE
+import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_DOES_NOT_EXIST
+import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.CM_HANDLE_INVALID_ID
+import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.RegistrationError.UNKNOWN_ERROR
+
class NetworkCmProxyDataServiceImplSpec extends Specification {
@@ -105,17 +111,6 @@
>> { new ResponseEntity<>(HttpStatus.CREATED) }
}
- def 'Write resource data for pass-through running from DMI using an invalid id.'() {
- when: 'write resource data is called'
- objectUnderTest.writeResourceDataPassThroughRunningForCmHandle('invalid cm handle name',
- 'testResourceId', CREATE,
- '{some-json}', 'application/json')
- then: 'exception is thrown'
- thrown(DataValidationException.class)
- and: 'DMI is not invoked'
- 0 * mockDmiDataOperations.writeResourceDataPassThroughRunningFromDmi(_, _, _, _, _)
- }
-
def 'Get resource data for pass-through operational from DMI.'() {
given: 'get data node is called'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
@@ -166,15 +161,6 @@
1 * mockInventoryPersistence.getYangResourcesModuleReferences('some-cm-handle')
}
- def 'Getting Yang Resources with an invalid #scenario.'() {
- when: 'yang resources is called'
- objectUnderTest.getYangResourcesModuleReferences('invalid cm handle with spaces')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'CPS module services is not invoked'
- 0 * mockInventoryPersistence.getYangResourcesModuleReferences(*_)
- }
-
def 'Get a cm handle.'() {
given: 'the system returns a yang modelled cm handle'
def dmiServiceName = 'some service name'
@@ -203,15 +189,6 @@
}
- def 'Get a cm handle with an invalid id.'() {
- when: 'getting cm handle details for a given cm handle id with an invalid name'
- objectUnderTest.getNcmpServiceCmHandle('invalid cm handle with spaces')
- then: 'an exception is thrown'
- thrown(DataValidationException)
- and: 'the yang model cm handle retriever is not invoked'
- 0 * mockInventoryPersistence.getYangModelCmHandle(*_)
- }
-
def 'Get cm handle public properties'() {
given: 'a yang modelled cm handle'
def dmiProperties = [new YangModelCmHandle.Property('prop', 'some DMI property')]
@@ -225,15 +202,6 @@
result == [ 'public prop' : 'some public prop' ]
}
- def 'Get cm handle public properties with an invalid id.'() {
- when: 'getting cm handle public properties for a given cm handle id with an invalid name'
- objectUnderTest.getCmHandlePublicProperties('invalid cm handle with spaces')
- then: 'an exception is thrown'
- thrown(DataValidationException)
- and: 'the yang model cm handle retriever is not invoked'
- 0 * mockInventoryPersistence.getYangModelCmHandle(*_)
- }
-
def 'Get cm handle composite state'() {
given: 'a yang modelled cm handle'
def compositeState = new CompositeState(cmHandleState: CmHandleState.ADVISED,
@@ -252,15 +220,6 @@
result == compositeState
}
- def 'Get cm handle composite state with an invalid id.'() {
- when: 'getting cm handle composite state for a given cm handle id with an invalid name'
- objectUnderTest.getCmHandleCompositeState('invalid cm handle with spaces')
- then: 'an exception is thrown'
- thrown(DataValidationException)
- and: 'the yang model cm handle retriever is not invoked'
- 0 * mockInventoryPersistence.getYangModelCmHandle(_)
- }
-
def 'Update resource data for pass-through running from dmi using POST #scenario DMI properties.'() {
given: 'cpsDataService returns valid datanode'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
index 3a82ee3..c4d0020 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy
@@ -15,7 +15,7 @@
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
+ * ============LICENSE_END=========================================================
*/
package org.onap.cps.ncmp.api.impl.operations
@@ -28,6 +28,7 @@
import org.onap.cps.ncmp.api.inventory.CmHandleState
import org.onap.cps.ncmp.api.inventory.CompositeState
import org.onap.cps.ncmp.api.inventory.InventoryPersistence
+import org.onap.cps.spi.utils.CpsValidator
import org.spockframework.spring.SpringBean
import spock.lang.Shared
import spock.lang.Specification
@@ -43,11 +44,13 @@
@SpringBean
InventoryPersistence mockInventoryPersistence = Mock()
+ def mockCpsValidator = Mock(CpsValidator)
+
@SpringBean
ObjectMapper spyObjectMapper = Spy()
@SpringBean
- DmiServiceUrlBuilder dmiServiceUrlBuilder = new DmiServiceUrlBuilder(new NcmpConfiguration.DmiProperties())
+ DmiServiceUrlBuilder dmiServiceUrlBuilder = new DmiServiceUrlBuilder(new NcmpConfiguration.DmiProperties(), mockCpsValidator)
def yangModelCmHandle = new YangModelCmHandle()
def static dmiServiceName = 'some service name'
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy
index 0d459fd..c713aad 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImplSpec.groovy
@@ -29,11 +29,11 @@
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.CpsAdminPersistenceService
import org.onap.cps.spi.FetchDescendantsOption
-import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.model.DataNode
import org.onap.cps.spi.model.ModuleDefinition
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.spi.utils.CpsValidator
import spock.lang.Shared
import spock.lang.Specification
@@ -56,8 +56,10 @@
def mockCpsAdminPersistenceService = Mock(CpsAdminPersistenceService)
+ def mockCpsValidator = Mock(CpsValidator)
+
def objectUnderTest = new InventoryPersistenceImpl(spiedJsonObjectMapper, mockCpsDataService, mockCpsModuleService,
- mockCpsDataPersistenceService, mockCpsAdminPersistenceService)
+ mockCpsDataPersistenceService, mockCpsAdminPersistenceService, mockCpsValidator)
def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
.format(OffsetDateTime.of(2022, 12, 31, 20, 30, 40, 1, ZoneOffset.UTC))
@@ -95,34 +97,29 @@
result.publicProperties == expectedPublicProperties
and: 'the state details are returned'
result.compositeState.cmHandleState == expectedCompositeState
+ and: 'the CM Handle ID is validated'
+ 1 * mockCpsValidator.validateNameCharacters(cmHandleId)
where: 'the following parameters are used'
scenario | childDataNodes || expectedDmiProperties || expectedPublicProperties || expectedCompositeState
'no properties' | [] || [] || [] || null
- 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")] || null
+ 'DMI and public properties' | childDataNodesForCmHandleWithAllProperties || [new YangModelCmHandle.Property("name1", "value1")] || [new YangModelCmHandle.Property("name2", "value2")] || null
'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || [] || null
'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")] || null
'with state details' | childDataNodesForCmHandleWithState || [] || [] || CmHandleState.ADVISED
}
- def "Retrieve CmHandle using datanode with invalid CmHandle id."() {
- when: 'retrieving the yang modelled cm handle with an invalid id'
- def result = objectUnderTest.getYangModelCmHandle('cm handle id with spaces')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the result is not returned'
- result == null
- }
-
- def "Handling missing service names as null CPS-1043."() {
+ def "Handling missing service names as null."() {
given: 'the cps data service returns a data node from the DMI registry with empty child and leaf attributes'
def dataNode = new DataNode(childDataNodes:[], leaves: [:])
mockCpsDataPersistenceService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', xpath, INCLUDE_ALL_DESCENDANTS) >> dataNode
when: 'retrieving the yang modelled cm handle'
def result = objectUnderTest.getYangModelCmHandle(cmHandleId)
- then: 'the service names ae returned as null'
+ then: 'the service names are returned as null'
result.dmiServiceName == null
result.dmiDataServiceName == null
result.dmiModelServiceName == null
+ and: 'the CM Handle ID is validated'
+ 1 * mockCpsValidator.validateNameCharacters(cmHandleId)
}
def 'Get a Cm Handle Composite State'() {
@@ -136,6 +133,8 @@
def result = objectUnderTest.getCmHandleState(cmHandleId)
then: 'result has returned the correct cm handle state'
result.cmHandleState == CmHandleState.ADVISED
+ and: 'the CM Handle ID is validated'
+ 1 * mockCpsValidator.validateNameCharacters(cmHandleId)
}
def 'Update Cm Handle with #scenario State'() {
@@ -187,6 +186,8 @@
def result = objectUnderTest.getYangResourcesModuleReferences('some-cmHandle-Id')
then: 'the returned result is a collection of module definitions'
assert result == moduleReferences
+ and: 'the CM Handle ID is validated'
+ 1 * mockCpsValidator.validateNameCharacters('some-cmHandle-Id')
}
def 'Save Cmhandle'() {
@@ -230,15 +231,8 @@
objectUnderTest.deleteSchemaSetWithCascade('validSchemaSetName')
then: 'the module service to delete schemaSet is invoked once'
1 * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'validSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
- }
-
- def 'Delete schema set with an invalid schema set name'() {
- when: 'the method to delete schema set is called with an invalid schema set name'
- objectUnderTest.deleteSchemaSetWithCascade('invalid SchemaSet name')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the module service to delete schemaSet is not called'
- 0 * mockCpsModuleService.deleteSchemaSet('NFP-Operational', 'sampleSchemaSetName', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
+ and: 'the CM Handle ID is validated'
+ 1 * mockCpsValidator.validateNameCharacters('validSchemaSetName')
}
def 'Get data node via xPath'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
index 2d99397..09f4550 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy
@@ -15,11 +15,12 @@
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
+ * ============LICENSE_END=========================================================
*/
package org.onap.cps.ncmp.api.utils
+import org.onap.cps.spi.utils.CpsValidator
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_RUNNING
@@ -38,7 +39,9 @@
NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties()
- def objectUnderTest = new DmiServiceUrlBuilder(dmiProperties)
+ def mockCpsValidator = Mock(CpsValidator)
+
+ def objectUnderTest = new DmiServiceUrlBuilder(dmiProperties, mockCpsValidator)
def 'Create the dmi service url with #scenario.'() {
given: 'uri variables'
diff --git a/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java
similarity index 82%
rename from cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java
rename to cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java
index f3774d9..0645831 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/utils/CpsValidatorImpl.java
@@ -18,27 +18,25 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.utils;
+package org.onap.cps.spi.impl.utils;
import com.google.common.collect.Lists;
import java.util.Collection;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.spi.exceptions.DataValidationException;
+import org.onap.cps.spi.utils.CpsValidator;
+import org.springframework.stereotype.Component;
@Slf4j
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class CpsValidator {
+@Component
+@RequiredArgsConstructor
+public class CpsValidatorImpl implements CpsValidator {
private static final char[] UNSUPPORTED_NAME_CHARACTERS = "!\" #$%&'()*+,./\\:;<=>?@[]^`{|}~".toCharArray();
- /**
- * Validate characters in names within cps.
- *
- * @param names names of data to be validated
- */
- public static void validateNameCharacters(final String... names) {
+ @Override
+ public void validateNameCharacters(final String... names) {
for (final String name : names) {
final Collection<Character> charactersOfName = Lists.charactersOf(name);
for (final char unsupportedCharacter : UNSUPPORTED_NAME_CHARACTERS) {
@@ -50,7 +48,4 @@
}
}
}
-
-
-
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy
similarity index 89%
rename from cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorSpec.groovy
rename to cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy
index ea7a5d6..ae2ff16 100644
--- a/cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/utils/CpsValidatorSpec.groovy
@@ -18,23 +18,25 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.utils
+package org.onap.cps.spi.impl.utils
import org.onap.cps.spi.exceptions.DataValidationException
import spock.lang.Specification
class CpsValidatorSpec extends Specification {
+ def objectUnderTest = new CpsValidatorImpl()
+
def 'Validating a valid string.'() {
when: 'the string is validated using a valid name'
- CpsValidator.validateNameCharacters('name-with-no-spaces')
+ objectUnderTest.validateNameCharacters('name-with-no-spaces')
then: 'no exception is thrown'
noExceptionThrown()
}
def 'Validating an invalid string.'() {
when: 'the string is validated using an invalid name'
- CpsValidator.validateNameCharacters(name)
+ objectUnderTest.validateNameCharacters(name)
then: 'a data validation exception is thrown'
def exceptionThrown = thrown(DataValidationException)
and: 'the error was encountered at the following index in #scenario'
@@ -44,5 +46,4 @@
'position 5' | 'name with spaces' || 'name with spaces invalid token encountered at position 5'
'position 9' | 'nameWith Space' || 'nameWith Space invalid token encountered at position 9'
}
-
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
index a67dfe5..56f4241 100755
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsAdminServiceImpl.java
@@ -30,7 +30,7 @@
import org.onap.cps.api.CpsDataService;
import org.onap.cps.spi.CpsAdminPersistenceService;
import org.onap.cps.spi.model.Anchor;
-import org.onap.cps.utils.CpsValidator;
+import org.onap.cps.spi.utils.CpsValidator;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
@@ -41,53 +41,54 @@
private final CpsAdminPersistenceService cpsAdminPersistenceService;
@Lazy
private final CpsDataService cpsDataService;
+ private final CpsValidator cpsValidator;
@Override
public void createDataspace(final String dataspaceName) {
- CpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(dataspaceName);
cpsAdminPersistenceService.createDataspace(dataspaceName);
}
@Override
public void deleteDataspace(final String dataspaceName) {
- CpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(dataspaceName);
cpsAdminPersistenceService.deleteDataspace(dataspaceName);
}
@Override
public void createAnchor(final String dataspaceName, final String schemaSetName, final String anchorName) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName, anchorName);
cpsAdminPersistenceService.createAnchor(dataspaceName, schemaSetName, anchorName);
}
@Override
public Collection<Anchor> getAnchors(final String dataspaceName) {
- CpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(dataspaceName);
return cpsAdminPersistenceService.getAnchors(dataspaceName);
}
@Override
public Collection<Anchor> getAnchors(final String dataspaceName, final String schemaSetName) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
return cpsAdminPersistenceService.getAnchors(dataspaceName, schemaSetName);
}
@Override
public Anchor getAnchor(final String dataspaceName, final String anchorName) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsAdminPersistenceService.getAnchor(dataspaceName, anchorName);
}
@Override
public void deleteAnchor(final String dataspaceName, final String anchorName) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
cpsDataService.deleteDataNodes(dataspaceName, anchorName, OffsetDateTime.now());
cpsAdminPersistenceService.deleteAnchor(dataspaceName, anchorName);
}
@Override
public Collection<String> queryAnchorNames(final String dataspaceName, final Collection<String> moduleNames) {
- CpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(dataspaceName);
final Collection<Anchor> anchors = cpsAdminPersistenceService.queryAnchors(dataspaceName, moduleNames);
return anchors.stream().map(Anchor::getName).collect(Collectors.toList());
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
index b6aa04b..88ebe3b 100755
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
@@ -31,7 +31,7 @@
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
-import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.CpsAdminService;
import org.onap.cps.api.CpsDataService;
@@ -43,7 +43,7 @@
import org.onap.cps.spi.model.Anchor;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.DataNodeBuilder;
-import org.onap.cps.utils.CpsValidator;
+import org.onap.cps.spi.utils.CpsValidator;
import org.onap.cps.utils.YangUtils;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -51,7 +51,7 @@
@Service
@Slf4j
-@AllArgsConstructor
+@RequiredArgsConstructor
public class CpsDataServiceImpl implements CpsDataService {
private static final String ROOT_NODE_XPATH = "/";
@@ -61,11 +61,12 @@
private final CpsAdminService cpsAdminService;
private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
private final NotificationService notificationService;
+ private final CpsValidator cpsValidator;
@Override
public void saveData(final String dataspaceName, final String anchorName, final String jsonData,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final DataNode dataNode = buildDataNode(dataspaceName, anchorName, ROOT_NODE_XPATH, jsonData);
cpsDataPersistenceService.storeDataNode(dataspaceName, anchorName, dataNode);
processDataUpdatedEventAsync(dataspaceName, anchorName, ROOT_NODE_XPATH, CREATE, observedTimestamp);
@@ -74,7 +75,7 @@
@Override
public void saveData(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final String jsonData, final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, parentNodeXpath, dataNode);
processDataUpdatedEventAsync(dataspaceName, anchorName, parentNodeXpath, CREATE, observedTimestamp);
@@ -83,7 +84,7 @@
@Override
public void saveListElements(final String dataspaceName, final String anchorName,
final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Collection<DataNode> listElementDataNodeCollection =
buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.addListElements(dataspaceName, anchorName, parentNodeXpath,
@@ -94,7 +95,7 @@
@Override
public void saveListElementsBatch(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final Collection<String> jsonDataList, final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Collection<Collection<DataNode>> listElementDataNodeCollections =
buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonDataList);
cpsDataPersistenceService.addMultipleLists(dataspaceName, anchorName, parentNodeXpath,
@@ -105,14 +106,14 @@
@Override
public DataNode getDataNode(final String dataspaceName, final String anchorName, final String xpath,
final FetchDescendantsOption fetchDescendantsOption) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsDataPersistenceService.getDataNode(dataspaceName, anchorName, xpath, fetchDescendantsOption);
}
@Override
public void updateNodeLeaves(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final String jsonData, final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService
.updateDataLeaves(dataspaceName, anchorName, dataNode.getXpath(), dataNode.getLeaves());
@@ -124,7 +125,7 @@
final String parentNodeXpath,
final String dataNodeUpdatesAsJson,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Collection<DataNode> dataNodeUpdates =
buildDataNodes(dataspaceName, anchorName,
parentNodeXpath, dataNodeUpdatesAsJson);
@@ -159,7 +160,7 @@
public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName,
final String parentNodeXpath, final String jsonData,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final DataNode dataNode = buildDataNode(dataspaceName, anchorName, parentNodeXpath, jsonData);
cpsDataPersistenceService.updateDataNodeAndDescendants(dataspaceName, anchorName, dataNode);
processDataUpdatedEventAsync(dataspaceName, anchorName, parentNodeXpath, UPDATE, observedTimestamp);
@@ -169,7 +170,7 @@
public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName,
final Map<String, String> nodesJsonData,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final List<DataNode> dataNodes = buildDataNodes(dataspaceName, anchorName, nodesJsonData);
cpsDataPersistenceService.updateDataNodesAndDescendants(dataspaceName, anchorName, dataNodes);
nodesJsonData.keySet().forEach(nodeXpath ->
@@ -180,7 +181,7 @@
@Override
public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final String jsonData, final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Collection<DataNode> newListElements =
buildDataNodes(dataspaceName, anchorName, parentNodeXpath, jsonData);
replaceListContent(dataspaceName, anchorName, parentNodeXpath, newListElements, observedTimestamp);
@@ -189,7 +190,7 @@
@Override
public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
final Collection<DataNode> dataNodes, final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
cpsDataPersistenceService.replaceListContent(dataspaceName, anchorName, parentNodeXpath, dataNodes);
processDataUpdatedEventAsync(dataspaceName, anchorName, parentNodeXpath, UPDATE, observedTimestamp);
}
@@ -197,7 +198,7 @@
@Override
public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
cpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, dataNodeXpath);
processDataUpdatedEventAsync(dataspaceName, anchorName, dataNodeXpath, DELETE, observedTimestamp);
}
@@ -205,7 +206,7 @@
@Override
public void deleteDataNodes(final String dataspaceName, final String anchorName,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
processDataUpdatedEventAsync(dataspaceName, anchorName, ROOT_NODE_XPATH, DELETE, observedTimestamp);
cpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName);
}
@@ -213,7 +214,7 @@
@Override
public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
final OffsetDateTime observedTimestamp) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
cpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, listNodeXpath);
processDataUpdatedEventAsync(dataspaceName, anchorName, listNodeXpath, DELETE, observedTimestamp);
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
index 20b4a23..b4890f4 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
@@ -24,7 +24,7 @@
import java.util.Collection;
import java.util.Map;
-import lombok.AllArgsConstructor;
+import lombok.RequiredArgsConstructor;
import org.onap.cps.api.CpsAdminService;
import org.onap.cps.api.CpsModuleService;
import org.onap.cps.spi.CascadeDeleteAllowed;
@@ -34,23 +34,24 @@
import org.onap.cps.spi.model.ModuleDefinition;
import org.onap.cps.spi.model.ModuleReference;
import org.onap.cps.spi.model.SchemaSet;
-import org.onap.cps.utils.CpsValidator;
+import org.onap.cps.spi.utils.CpsValidator;
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("CpsModuleServiceImpl")
-@AllArgsConstructor
+@RequiredArgsConstructor
public class CpsModuleServiceImpl implements CpsModuleService {
private final CpsModulePersistenceService cpsModulePersistenceService;
private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
private final CpsAdminService cpsAdminService;
+ private final CpsValidator cpsValidator;
@Override
public void createSchemaSet(final String dataspaceName, final String schemaSetName,
final Map<String, String> yangResourcesNameToContentMap) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
final var yangTextSchemaSourceSet
= YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap);
cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
@@ -61,7 +62,7 @@
public void createSchemaSetFromModules(final String dataspaceName, final String schemaSetName,
final Map<String, String> newModuleNameToContentMap,
final Collection<ModuleReference> allModuleReferences) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
cpsModulePersistenceService.storeSchemaSetFromModules(dataspaceName, schemaSetName,
newModuleNameToContentMap, allModuleReferences);
@@ -69,7 +70,7 @@
@Override
public SchemaSet getSchemaSet(final String dataspaceName, final String schemaSetName) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
final var yangTextSchemaSourceSet = yangTextSchemaSourceSetCache
.get(dataspaceName, schemaSetName);
return SchemaSet.builder().name(schemaSetName).dataspaceName(dataspaceName)
@@ -80,7 +81,7 @@
@Transactional
public void deleteSchemaSet(final String dataspaceName, final String schemaSetName,
final CascadeDeleteAllowed cascadeDeleteAllowed) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
final Collection<Anchor> anchors = cpsAdminService.getAnchors(dataspaceName, schemaSetName);
if (!anchors.isEmpty() && isCascadeDeleteProhibited(cascadeDeleteAllowed)) {
throw new SchemaSetInUseException(dataspaceName, schemaSetName);
@@ -95,21 +96,21 @@
@Override
public Collection<ModuleReference> getYangResourceModuleReferences(final String dataspaceName) {
- CpsValidator.validateNameCharacters(dataspaceName);
+ cpsValidator.validateNameCharacters(dataspaceName);
return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName);
}
@Override
public Collection<ModuleReference> getYangResourcesModuleReferences(final String dataspaceName,
final String anchorName) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName, anchorName);
}
@Override
public Collection<ModuleDefinition> getModuleDefinitionsByAnchorName(final String dataspaceName,
final String anchorName) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsModulePersistenceService.getYangResourceDefinitions(dataspaceName, anchorName);
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java b/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java
index c2003d6..7b9043a 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/CpsQueryServiceImpl.java
@@ -1,6 +1,6 @@
/*
- * ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021-2022 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,24 +21,25 @@
package org.onap.cps.api.impl;
import java.util.Collection;
+import lombok.RequiredArgsConstructor;
import org.onap.cps.api.CpsQueryService;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
-import org.onap.cps.utils.CpsValidator;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.onap.cps.spi.utils.CpsValidator;
import org.springframework.stereotype.Service;
@Service
+@RequiredArgsConstructor
public class CpsQueryServiceImpl implements CpsQueryService {
- @Autowired
- private CpsDataPersistenceService cpsDataPersistenceService;
+ private final CpsDataPersistenceService cpsDataPersistenceService;
+ private final CpsValidator cpsValidator;
@Override
public Collection<DataNode> queryDataNodes(final String dataspaceName, final String anchorName,
final String cpsPath, final FetchDescendantsOption fetchDescendantsOption) {
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
+ cpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption);
}
}
diff --git a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
index fb881a9..0f620b0 100644
--- a/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
+++ b/cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
@@ -1,7 +1,8 @@
/*
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* Copyright (C) 2021 Pantheon.tech
* Modifications Copyright (C) 2022 Bell Canada
+ * Modifications Copyright (C) 2022 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,11 +24,11 @@
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.Map;
+import lombok.RequiredArgsConstructor;
import org.onap.cps.spi.CpsModulePersistenceService;
-import org.onap.cps.utils.CpsValidator;
+import org.onap.cps.spi.utils.CpsValidator;
import org.onap.cps.yang.YangTextSchemaSourceSet;
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
@@ -39,10 +40,11 @@
*/
@Service
@CacheConfig(cacheNames = {"yangSchema"})
+@RequiredArgsConstructor
public class YangTextSchemaSourceSetCache {
- @Autowired
- private CpsModulePersistenceService cpsModulePersistenceService;
+ private final CpsModulePersistenceService cpsModulePersistenceService;
+ private final CpsValidator cpsValidator;
/**
* Cache YangTextSchemaSourceSet.
@@ -53,7 +55,7 @@
*/
@Cacheable(key = "#p0.concat('-').concat(#p1)")
public YangTextSchemaSourceSet get(final String dataspaceName, final String schemaSetName) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
final Map<String, String> yangResourceNameToContent =
cpsModulePersistenceService.getYangSchemaResources(dataspaceName, schemaSetName);
return YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent);
@@ -71,7 +73,7 @@
@CanIgnoreReturnValue
public YangTextSchemaSourceSet updateCache(final String dataspaceName, final String schemaSetName,
final YangTextSchemaSourceSet yangTextSchemaSourceSet) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
return yangTextSchemaSourceSet;
}
@@ -84,7 +86,7 @@
*/
@CacheEvict(key = "#p0.concat('-').concat(#p1)")
public void removeFromCache(final String dataspaceName, final String schemaSetName) {
- CpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+ cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
// Spring provides implementation for removing object from cache
}
diff --git a/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java b/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java
new file mode 100644
index 0000000..c7ce8fc
--- /dev/null
+++ b/cps-service/src/main/java/org/onap/cps/spi/utils/CpsValidator.java
@@ -0,0 +1,31 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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.spi.utils;
+
+public interface CpsValidator {
+
+ /**
+ * Validate characters in names within cps.
+ *
+ * @param names names of data to be validated
+ */
+ void validateNameCharacters(final String... names);
+}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
index 41fcb29..2979c09 100755
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy
@@ -24,30 +24,24 @@
import org.onap.cps.api.CpsDataService
import org.onap.cps.spi.CpsAdminPersistenceService
-import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.model.Anchor
+import org.onap.cps.spi.utils.CpsValidator
import spock.lang.Specification
import java.time.OffsetDateTime
class CpsAdminServiceImplSpec extends Specification {
def mockCpsAdminPersistenceService = Mock(CpsAdminPersistenceService)
def mockCpsDataService = Mock(CpsDataService)
- def objectUnderTest = new CpsAdminServiceImpl(mockCpsAdminPersistenceService, mockCpsDataService)
+ def mockCpsValidator = Mock(CpsValidator)
+ def objectUnderTest = new CpsAdminServiceImpl(mockCpsAdminPersistenceService, mockCpsDataService,mockCpsValidator)
def 'Create dataspace method invokes persistence service.'() {
when: 'create dataspace method is invoked'
objectUnderTest.createDataspace('someDataspace')
then: 'the persistence service method is invoked with same parameters'
1 * mockCpsAdminPersistenceService.createDataspace('someDataspace')
- }
-
- def 'Create a dataspace with an invalid dataspace name.'() {
- when: 'create dataspace method is invoked with incorrectly named dataspace'
- objectUnderTest.createDataspace('Dataspace Name with spaces')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsAdminPersistenceService.createDataspace(_)
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
}
def 'Create anchor method invokes persistence service.'() {
@@ -55,76 +49,44 @@
objectUnderTest.createAnchor('someDataspace', 'someSchemaSet', 'someAnchorName')
then: 'the persistence service method is invoked with same parameters'
1 * mockCpsAdminPersistenceService.createAnchor('someDataspace', 'someSchemaSet', 'someAnchorName')
- }
-
- def 'Create an anchor with an invalid anchor name.'() {
- when: 'create anchor method is invoked with incorrectly named dataspace'
- objectUnderTest.createAnchor('someDataspace', 'someSchemaSet', 'Anchor Name With Spaces')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsAdminPersistenceService.createAnchor(_, _, _)
+ and: 'the CpsValidator is called on the dataspaceName, schemaSetName and anchorName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet', 'someAnchorName')
}
def 'Retrieve all anchors for dataspace.'() {
- given: 'that anchor is associated with the dataspace'
+ given: 'that an anchor is associated with the dataspace'
def anchors = [new Anchor()]
mockCpsAdminPersistenceService.getAnchors('someDataspace') >> anchors
- expect: 'the collection provided by persistence service is returned as result'
- objectUnderTest.getAnchors('someDataspace') == anchors
- }
-
- def 'Retrieve all anchors with an invalid dataspace name.'() {
- when: 'get anchors is invoked with an invalid dataspace name'
- objectUnderTest.getAnchors('Dataspace name with spaces')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'cps admin persistence get anchors is not invoked'
- 0 * mockCpsAdminPersistenceService.getAnchors(_)
+ when: 'get Anchors is called for a dataspace name'
+ def result = objectUnderTest.getAnchors('someDataspace')
+ then: 'the collection provided by persistence service is returned as result'
+ result == anchors
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
}
def 'Retrieve all anchors for schema-set.'() {
given: 'that anchor is associated with the dataspace and schemaset'
def anchors = [new Anchor()]
mockCpsAdminPersistenceService.getAnchors('someDataspace', 'someSchemaSet') >> anchors
- expect: 'the collection provided by persistence service is returned as result'
- objectUnderTest.getAnchors('someDataspace', 'someSchemaSet') == anchors
+ when: 'get anchors is called for a dataspace name and schema set name'
+ def result = objectUnderTest.getAnchors('someDataspace', 'someSchemaSet')
+ then: 'the collection provided by persistence service is returned as result'
+ result == anchors
+ and: 'the CpsValidator is called on the dataspaceName, schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
}
- def 'Retrieve all anchors for schema-set with invalid #scenario.'() {
- when: 'the collection provided by persistence service is returned as result'
- objectUnderTest.getAnchors(dataspaceName, schemaSetName)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'cps admin persistence get anchors is not invoked'
- 0 * mockCpsAdminPersistenceService.getAnchors(_, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
- }
-
def 'Retrieve anchor for dataspace and provided anchor name.'() {
given: 'that anchor name is associated with the dataspace'
Anchor anchor = new Anchor()
mockCpsAdminPersistenceService.getAnchor('someDataspace','someAnchor') >> anchor
- expect: 'the anchor provided by persistence service is returned as result'
- assert objectUnderTest.getAnchor('someDataspace','someAnchor') == anchor
- }
-
- def 'Retrieve anchor with invalid #scenario.'() {
- when: 'get anchors is invoked with an invalid dataspace name'
- objectUnderTest.getAnchor(dataspaceName, anchorName)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'cps admin persistence get anchor is not invoked'
- 0 * mockCpsAdminPersistenceService.getAnchor(_, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
+ when: 'get anchor is called for a dataspace name and anchor name'
+ def result = objectUnderTest.getAnchor('someDataspace','someAnchor')
+ then: 'the anchor provided by persistence service is returned as result'
+ result == anchor
+ and: 'the CpsValidator is called on the dataspaceName, anchorName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchor')
}
def 'Delete anchor.'() {
@@ -134,39 +96,19 @@
1 * mockCpsDataService.deleteDataNodes('someDataspace','someAnchor', _ as OffsetDateTime )
and: 'the persistence service method is invoked with same parameters to delete anchor'
1 * mockCpsAdminPersistenceService.deleteAnchor('someDataspace','someAnchor')
- }
-
- def 'Delete anchor with invalid #scenario.'() {
- when: 'delete anchor is invoked'
- objectUnderTest.deleteAnchor(dataspaceName, anchorName)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'delete data nodes is invoked on the data service with expected parameters'
- 0 * mockCpsDataService.deleteDataNodes(_,_, _ as OffsetDateTime )
- and: 'the persistence service method is invoked with same parameters to delete anchor'
- 0 * mockCpsAdminPersistenceService.deleteAnchor(_,_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
+ and: 'the CpsValidator is called on the dataspaceName, anchorName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someAnchor')
}
def 'Query all anchor identifiers for a dataspace and module names.'() {
given: 'the persistence service is invoked with the expected parameters and returns a list of anchors'
mockCpsAdminPersistenceService.queryAnchors('some-dataspace-name', ['some-module-name']) >> [new Anchor(name:'some-anchor-identifier')]
- expect: 'get anchor identifiers returns the same anchor identifier returned by the persistence layer'
- objectUnderTest.queryAnchorNames('some-dataspace-name', ['some-module-name']) == ['some-anchor-identifier']
-
- }
-
- def 'Query all anchor identifiers for a dataspace and module names with an invalid dataspace name.'() {
- when: 'delete anchor is invoked'
- objectUnderTest.queryAnchorNames('some dataspace name', _ as Collection<String>)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'delete data nodes is not invoked'
- 0 * mockCpsAdminPersistenceService.queryAnchors(_, _)
+ when: 'query anchor names is called using a dataspace name and module name'
+ def result = objectUnderTest.queryAnchorNames('some-dataspace-name', ['some-module-name'])
+ then: 'get anchor identifiers returns the same anchor identifier returned by the persistence layer'
+ result == ['some-anchor-identifier']
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('some-dataspace-name')
}
def 'Delete dataspace.'() {
@@ -174,14 +116,7 @@
objectUnderTest.deleteDataspace('someDataspace')
then: 'associated persistence service method is invoked with correct parameter'
1 * mockCpsAdminPersistenceService.deleteDataspace('someDataspace')
- }
-
- def 'Delete dataspace with invalid dataspace id.'() {
- when: 'delete dataspace is invoked'
- objectUnderTest.deleteDataspace('some dataspace name')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'associated persistence service method is not invoked'
- 0 * mockCpsAdminPersistenceService.deleteDataspace(_)
+ and: 'the CpsValidator is called on the dataspaceName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace')
}
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index a53706a..b60e7e8 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -35,6 +35,7 @@
import org.onap.cps.yang.YangTextSchemaSourceSet
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
import spock.lang.Specification
+import org.onap.cps.spi.utils.CpsValidator
import java.time.OffsetDateTime
import java.util.stream.Collectors
@@ -44,9 +45,10 @@
def mockCpsAdminService = Mock(CpsAdminService)
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
def mockNotificationService = Mock(NotificationService)
+ def mockCpsValidator = Mock(CpsValidator)
def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockCpsAdminService,
- mockYangTextSchemaSourceSetCache, mockNotificationService)
+ mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator)
def setup() {
mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
@@ -67,26 +69,12 @@
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.storeDataNode(dataspaceName, anchorName,
{ dataNode -> dataNode.xpath == '/test-tree' })
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/', Operation.CREATE, observedTimestamp)
}
- def 'Saving json data with invalid #scenario.'() {
- when: 'save data method is invoked with invalid #scenario'
- objectUnderTest.saveData(dataspaceName, anchorName, _ as String, observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.storeDataNode(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Saving child data fragment under existing node.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -96,26 +84,12 @@
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName, '/test-tree',
{ dataNode -> dataNode.xpath == '/test-tree/branch[@name=\'New\']' })
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/test-tree', Operation.CREATE, observedTimestamp)
}
- def 'Saving child data fragment under existing node with invalid #scenario.'() {
- when: 'save data method is invoked with test-tree and an invalid #scenario'
- objectUnderTest.saveData(dataspaceName, anchorName, '/test-tree', _ as String, observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.addChildDataNode(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Saving list element data fragment under existing node.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -132,6 +106,8 @@
}
}
)
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/test-tree', Operation.UPDATE, observedTimestamp)
}
@@ -166,20 +142,6 @@
thrown(DataValidationException)
}
- def 'Saving list element data fragment with invalid #scenario.'() {
- when: 'save data method is invoked with an invalid #scenario'
- objectUnderTest.saveListElements(dataspaceName, anchorName, '/test-tree', _ as String, observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'add list elements persistence method is not invoked'
- 0 * mockCpsDataPersistenceService.addListElements(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Get data node with option #fetchDescendantsOption.'() {
def xpath = '/xpath'
def dataNode = new DataNodeBuilder().withXpath(xpath).build()
@@ -191,20 +153,6 @@
fetchDescendantsOption << [FetchDescendantsOption.OMIT_DESCENDANTS, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS]
}
- def 'Get data node with option invalid #scenario.'() {
- when: 'get data node is invoked with #scenario'
- objectUnderTest.getDataNode(dataspaceName, anchorName, '/test-tree', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'get data node persistence service is not invoked'
- 0 * mockCpsDataPersistenceService.getDataNode(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Update data node leaves: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -212,6 +160,8 @@
objectUnderTest.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath, jsonData, observedTimestamp)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, expectedNodeXpath, leaves)
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, parentNodeXpath, Operation.UPDATE, observedTimestamp)
where: 'following parameters were used'
@@ -220,22 +170,6 @@
'level 2 node' | '/test-tree' | '{"branch": [{"name":"Name"}]}' || '/test-tree/branch[@name=\'Name\']' | ['name': 'Name']
}
- def 'Update data node with invalid #scenario.'() {
- when: 'update data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
- objectUnderTest.updateNodeLeaves(dataspaceName, anchorName, '/', '{"test-tree": {"branch": []}}', observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.updateDataLeaves(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Update list-element data node with : #scenario.'() {
given: 'schema set for given anchor and dataspace references bookstore model'
setupSchemaSetMocks('bookstore.yang')
@@ -261,28 +195,12 @@
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName,
"/bookstore/categories[@code='01']", ['name':'Romance', 'code': '01'])
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'the data updated event is sent to the notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/bookstore', Operation.UPDATE, observedTimestamp)
}
- def 'Update Bookstore node leaves with invalid #scenario' () {
- when: 'update data method is invoked with an invalid #scenario'
- objectUnderTest.updateNodeLeavesAndExistingDescendantLeaves(dataspaceName, anchorName,
- '/bookstore', _ as String, observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.updateDataLeaves(*_)
- and: 'the data updated event is not sent to the notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
-
def 'Replace data node using singular data node: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -293,6 +211,8 @@
{ dataNode -> dataNode.xpath == expectedNodeXpath })
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, parentNodeXpath, Operation.UPDATE, observedTimestamp)
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'following parameters were used'
scenario | parentNodeXpath | jsonData || expectedNodeXpath
'top level node' | '/' | '{"test-tree": {"branch": []}}' || '/test-tree'
@@ -310,44 +230,14 @@
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, nodesJsonData.keySet()[0], Operation.UPDATE, observedTimestamp)
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, nodesJsonData.keySet()[1], Operation.UPDATE, observedTimestamp)
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'following parameters were used'
scenario | nodesJsonData || expectedNodeXpath
'top level node' | ['/' : '{"test-tree": {"branch": []}}', '/test-tree' : '{"branch": [{"name":"Name"}]}'] || ["/test-tree", "/test-tree/branch[@name='Name']"]
'level 2 node' | ['/test-tree' : '{"branch": [{"name":"Name"}]}', '/test-tree/branch[@name=\'Name\']':'{"nest":{"name":"nestName"}}'] || ["/test-tree/branch[@name='Name']", "/test-tree/branch[@name='Name']/nest"]
}
- def 'Replace data node using singular data node with invalid #scenario.'() {
- when: 'replace data method is invoked with invalid #scenario'
- objectUnderTest.updateDataNodeAndDescendants(dataspaceName, anchorName, '/', _ as String, observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.updateDataNodeAndDescendants(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
- def 'Replace data node using multiple data nodes with invalid #scenario.'() {
- when: 'replace data method is invoked with invalid #scenario'
- objectUnderTest.updateDataNodesAndDescendants(dataspaceName, anchorName, ['/': _ as String], observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.updateDataNodesAndDescendants(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Replace list content data fragment under parent node.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -364,6 +254,8 @@
}
}
)
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName twice'
+ 2 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/test-tree', Operation.UPDATE, observedTimestamp)
}
@@ -378,22 +270,6 @@
thrown(DataValidationException)
}
- def 'Replace whole list content with an invalid #scenario.'() {
- when: 'replace list data method is invoked with invalid #scenario'
- objectUnderTest.replaceListContent(dataspaceName, anchorName, '/test-tree', _ as Collection<DataNode>, observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.replaceListContent(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Delete list element under existing node.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -401,27 +277,12 @@
objectUnderTest.deleteListOrListElement(dataspaceName, anchorName, '/test-tree/branch', observedTimestamp)
then: 'the persistence service method is invoked with correct parameters'
1 * mockCpsDataPersistenceService.deleteListDataNode(dataspaceName, anchorName, '/test-tree/branch')
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/test-tree/branch', Operation.DELETE, observedTimestamp)
}
-
- def 'Delete list element with an invalid #scenario.'() {
- when: 'delete list data method is invoked with with invalid #scenario'
- objectUnderTest.deleteDataNode(dataspaceName, anchorName, '/data-node', observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.deleteListDataNode(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Delete data node under anchor and dataspace.'() {
given: 'schema set for given anchor and dataspace references test tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -429,26 +290,12 @@
objectUnderTest.deleteDataNode(dataspaceName, anchorName, '/data-node', observedTimestamp)
then: 'the persistence service method is invoked with the correct parameters'
1 * mockCpsDataPersistenceService.deleteDataNode(dataspaceName, anchorName, '/data-node')
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'data updated event is sent to notification service'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/data-node', Operation.DELETE, observedTimestamp)
}
- def 'Delete data node with an invalid #scenario.'() {
- when: 'delete data node method is invoked with invalid #scenario'
- objectUnderTest.deleteDataNode(dataspaceName, anchorName, '/data-node', observedTimestamp)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsDataPersistenceService.deleteDataNode(*_)
- and: 'data updated event is not sent to notification service'
- 0 * mockNotificationService.processDataUpdatedEvent(*_)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
def 'Delete all data nodes for a given anchor and dataspace.'() {
given: 'schema set for given anchor and dataspace references test tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -456,6 +303,8 @@
objectUnderTest.deleteDataNodes(dataspaceName, anchorName, observedTimestamp)
then: 'data updated event is sent to notification service before the delete'
1 * mockNotificationService.processDataUpdatedEvent(dataspaceName, anchorName, '/', Operation.DELETE, observedTimestamp)
+ and: 'the CpsValidator is called on the dataspaceName and AnchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
and: 'the persistence service method is invoked with the correct parameters'
1 * mockCpsDataPersistenceService.deleteDataNodes(dataspaceName, anchorName)
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
index 429de7d..690578e 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
@@ -1,5 +1,5 @@
/*
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* Copyright (C) 2020-2022 Nordix Foundation
* Modifications Copyright (C) 2020-2021 Pantheon.tech
* Modifications Copyright (C) 2020-2022 Bell Canada.
@@ -25,9 +25,9 @@
import org.onap.cps.TestUtils
import org.onap.cps.api.CpsAdminService
import org.onap.cps.spi.CpsModulePersistenceService
-import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.exceptions.ModelValidationException
import org.onap.cps.spi.exceptions.SchemaSetInUseException
+import org.onap.cps.spi.utils.CpsValidator
import org.onap.cps.spi.model.Anchor
import org.onap.cps.spi.model.ModuleReference
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
@@ -40,8 +40,9 @@
def mockCpsModulePersistenceService = Mock(CpsModulePersistenceService)
def mockCpsAdminService = Mock(CpsAdminService)
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
+ def mockCpsValidator = Mock(CpsValidator)
- def objectUnderTest = new CpsModuleServiceImpl(mockCpsModulePersistenceService, mockYangTextSchemaSourceSetCache, mockCpsAdminService)
+ def objectUnderTest = new CpsModuleServiceImpl(mockCpsModulePersistenceService, mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator)
def 'Create schema set.'() {
given: 'Valid yang resource as name-to-content map'
@@ -50,20 +51,8 @@
objectUnderTest.createSchemaSet('someDataspace', 'someSchemaSet', yangResourcesNameToContentMap)
then: 'Parameters are validated and processing is delegated to persistence service'
1 * mockCpsModulePersistenceService.storeSchemaSet('someDataspace', 'someSchemaSet', yangResourcesNameToContentMap)
- }
-
- def 'Create a schema set with an invalid #scenario.'() {
- when: 'create dataspace method is invoked with incorrectly named dataspace'
- objectUnderTest.createSchemaSet(dataspaceName, schemaSetName, _ as Map<String, String>)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsModulePersistenceService.storeSchemaSet(_, _, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
}
def 'Create schema set from new modules and existing modules.'() {
@@ -74,20 +63,8 @@
objectUnderTest.createSchemaSetFromModules("someDataspaceName", "someSchemaSetName", [newModule: "newContent"], listOfExistingModulesModuleReference)
then: 'processing is delegated to persistence service'
1 * mockCpsModulePersistenceService.storeSchemaSetFromModules("someDataspaceName", "someSchemaSetName", [newModule: "newContent"], listOfExistingModulesModuleReference)
- }
-
- def 'Create schema set from new modules and existing modules with invalid #scenario.'() {
- when: 'create dataspace method is invoked with incorrectly named dataspace'
- objectUnderTest.createSchemaSetFromModules(dataspaceName, schemaSetName, _ as Map<String, String>, _ as Collection<ModuleReference>)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsModulePersistenceService.storeSchemaSetFromModules(_, _, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspaceName', 'someSchemaSetName')
}
def 'Create schema set from invalid resources'() {
@@ -110,20 +87,8 @@
result.getName().contains('someSchemaSet')
result.getDataspaceName().contains('someDataspace')
result.getModuleReferences().contains(new ModuleReference('stores', '2020-09-15', 'org:onap:ccsdk:sample'))
- }
-
- def 'Get a schema set with an invalid #scenario'() {
- when: 'create dataspace method is invoked with incorrectly named dataspace'
- objectUnderTest.getSchemaSet(dataspaceName, schemaSetName)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the yang resource cache is not invoked'
- 0 * mockYangTextSchemaSourceSetCache.get(_, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspace', 'someSchemaSet')
}
def 'Delete schema-set when cascade is allowed.'() {
@@ -140,6 +105,8 @@
1 * mockYangTextSchemaSourceSetCache.removeFromCache('my-dataspace', 'my-schemaset')
and: 'orphan yang resources are deleted'
1 * mockCpsModulePersistenceService.deleteUnusedYangResourceModules()
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace', _)
where: 'following parameters are used'
numberOfAnchors << [0, 3]
}
@@ -157,6 +124,8 @@
1 * mockYangTextSchemaSourceSetCache.removeFromCache('my-dataspace', 'my-schemaset')
and: 'orphan yang resources are deleted'
1 * mockCpsModulePersistenceService.deleteUnusedYangResourceModules()
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
}
def 'Delete schema-set when cascade is prohibited and schema-set has anchors.'() {
@@ -168,26 +137,6 @@
thrown(SchemaSetInUseException)
}
- def 'Delete a schema set with an invalid #scenario.'() {
- when: 'create dataspace method is invoked with incorrectly named dataspace'
- objectUnderTest.deleteSchemaSet(dataspaceName, schemaSetName, CASCADE_DELETE_ALLOWED)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'anchor deletion is called 0 times'
- 0 * mockCpsAdminService.deleteAnchor(_, _)
- and: 'the delete schema set persistence service method is not invoked'
- 0 * mockCpsModulePersistenceService.deleteSchemaSet(_, _, _)
- and: 'schema set will be removed from the cache is not invoked'
- 0 * mockYangTextSchemaSourceSetCache.removeFromCache(_, _)
- and: 'orphan yang resources are deleted is not invoked'
- 0 * mockCpsModulePersistenceService.deleteUnusedYangResourceModules()
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
- }
-
def createAnchors(int anchorCount) {
def anchors = []
(0..<anchorCount).each { anchors.add(new Anchor("my-anchor-$it", 'my-dataspace', 'my-schemaset')) }
@@ -198,40 +147,24 @@
given: 'an already present module reference'
def moduleReferences = [new ModuleReference('some module name','some revision name')]
mockCpsModulePersistenceService.getYangResourceModuleReferences('someDataspaceName') >> moduleReferences
- expect: 'the list provided by persistence service is returned as result'
- objectUnderTest.getYangResourceModuleReferences('someDataspaceName') == moduleReferences
+ when: 'get yang resource module references is called'
+ def result = objectUnderTest.getYangResourceModuleReferences('someDataspaceName')
+ then: 'the list provided by persistence service is returned as result'
+ result == moduleReferences
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspaceName')
}
- def 'Get all yang resources module references given an invalid dataspace name.'() {
- when: 'the get yang resources module references method is invoked with an invalid dataspace name'
- objectUnderTest.getYangResourceModuleReferences('dataspace name with spaces')
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsModulePersistenceService.getYangResourceModuleReferences(_)
- }
-
-
def 'Get all yang resources module references for the given dataspace name and anchor name.'() {
given: 'the module store service service returns a list module references'
def moduleReferences = [new ModuleReference()]
mockCpsModulePersistenceService.getYangResourceModuleReferences('someDataspaceName', 'someAnchorName') >> moduleReferences
- expect: 'the list provided by persistence service is returned as result'
- objectUnderTest.getYangResourcesModuleReferences('someDataspaceName', 'someAnchorName') == moduleReferences
- }
-
- def 'Get all yang resources module references given an invalid #scenario.'() {
- when: 'the get yang resources module references method is invoked with invalid #scenario'
- objectUnderTest.getYangResourcesModuleReferences(dataspaceName, anchorName)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service method is not invoked'
- 0 * mockCpsModulePersistenceService.getYangResourceModuleReferences(_, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
+ when: 'get yang resource module references is called for dataspace name and anchor name'
+ def result = objectUnderTest.getYangResourcesModuleReferences('someDataspaceName', 'someAnchorName')
+ then: 'the list provided by persistence service is returned as result'
+ result == moduleReferences
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('someDataspaceName', 'someAnchorName')
}
def 'Identifying new module references'(){
@@ -248,5 +181,7 @@
objectUnderTest.getModuleDefinitionsByAnchorName('some-dataspace-name', 'some-anchor-name')
then: 'CPS module persistence service is invoked the correct number of times'
1 * mockCpsModulePersistenceService.getYangResourceDefinitions('some-dataspace-name', 'some-anchor-name')
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('some-dataspace-name', 'some-anchor-name')
}
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy
index b7fec85..8b232b4 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy
@@ -1,5 +1,5 @@
/*
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* Copyright (C) 2021-2022 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,17 +22,14 @@
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.FetchDescendantsOption
-import org.onap.cps.spi.exceptions.DataValidationException
+import org.onap.cps.spi.utils.CpsValidator
import spock.lang.Specification
class CpsQueryServiceImplSpec extends Specification {
def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
+ def mockCpsValidator = Mock(CpsValidator)
- def objectUnderTest = new CpsQueryServiceImpl()
-
- def setup() {
- objectUnderTest.cpsDataPersistenceService = mockCpsDataPersistenceService
- }
+ def objectUnderTest = new CpsQueryServiceImpl(mockCpsDataPersistenceService, mockCpsValidator)
def 'Query data nodes by cps path with #fetchDescendantsOption.'() {
given: 'a dataspace name, an anchor name and a cps path'
@@ -43,22 +40,10 @@
objectUnderTest.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption)
then: 'the persistence service is called once with the correct parameters'
1 * mockCpsDataPersistenceService.queryDataNodes(dataspaceName, anchorName, cpsPath, fetchDescendantsOption)
+ and: 'the CpsValidator is called on the dataspaceName, schemaSetName and anchorName'
+ 1 * mockCpsValidator.validateNameCharacters(dataspaceName, anchorName)
where: 'all fetch descendants options are supported'
fetchDescendantsOption << [FetchDescendantsOption.OMIT_DESCENDANTS, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS]
}
- def 'Query data nodes by cps path with invalid #scenario.'() {
- when: 'queryDataNodes is invoked'
- objectUnderTest.queryDataNodes(dataspaceName, anchorName, '/cps-path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
- then: 'a data validation exception is thrown'
- thrown(DataValidationException)
- and: 'the persistence service is not invoked'
- 0 * mockCpsDataPersistenceService.queryDataNodes(_, _, _, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | anchorName
- 'dataspace name' | 'dataspace names with spaces' | 'anchorName'
- 'anchor name' | 'dataspaceName' | 'anchor name with spaces'
- 'dataspace and anchor name' | 'dataspace name with spaces' | 'anchor name with spaces'
- }
-
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
index 5238952..2fc85aa 100755
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation.
+ * Copyright (C) 2021-2022 Nordix Foundation.
* Modifications Copyright (C) 2021-2022 Bell Canada.
* Modifications Copyright (C) 2021 Pantheon.tech
* ================================================================================
@@ -8,7 +8,7 @@
* 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
+ * 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,
@@ -28,6 +28,7 @@
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.CpsModulePersistenceService
import org.onap.cps.spi.model.Anchor
+import org.onap.cps.spi.utils.CpsValidator
import org.onap.cps.utils.YangUtils
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
import spock.lang.Specification
@@ -38,10 +39,11 @@
def mockCpsAdminService = Mock(CpsAdminService)
def mockNotificationService = Mock(NotificationService)
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
+ def mockCpsValidator = Mock(CpsValidator)
def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,
- mockYangTextSchemaSourceSetCache,mockCpsAdminService )
+ mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator)
def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAdminService,
- mockYangTextSchemaSourceSetCache, mockNotificationService)
+ mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator)
def dataspaceName = 'someDataspace'
def anchorName = 'someAnchor'
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
index 06c675a..a9f50ee 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
@@ -1,5 +1,5 @@
/*
- * ============LICENSE_START=======================================================
+ * ============LICENSE_START=======================================================
* Copyright (C) 2022 Bell Canada
* Modifications Copyright (C) 2022 Nordix Foundation
* ================================================================================
@@ -23,7 +23,6 @@
import org.onap.cps.TestUtils
import org.onap.cps.spi.CpsModulePersistenceService
-import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.yang.YangTextSchemaSourceSet
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
import org.spockframework.spring.SpringBean
@@ -35,6 +34,8 @@
import org.springframework.cache.caffeine.CaffeineCacheManager
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
+import org.onap.cps.spi.utils.CpsValidator
+
@SpringBootTest
@EnableCaching
@@ -44,6 +45,9 @@
@SpringBean
CpsModulePersistenceService mockModuleStoreService = Mock()
+ @SpringBean
+ CpsValidator mockCpsValidator = Mock(CpsValidator)
+
@Autowired
YangTextSchemaSourceSetCache objectUnderTest
@@ -74,6 +78,8 @@
assert cachedValue.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
and: 'the response is as expected'
assert result.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
}
def 'Cache Hit: Respond from cache'() {
@@ -90,20 +96,6 @@
0 * mockModuleStoreService.getYangSchemaResources(_, _)
}
- def 'Cache Hit: with invalid #scenario'() {
- when: 'schema-set information is asked'
- objectUnderTest.get(dataspaceName, schemaSetName)
- then: 'an data validation exception is thrown'
- thrown(DataValidationException)
- and: 'module persistence is not invoked'
- 0 * mockModuleStoreService.getYangSchemaResources(_, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
- }
-
def 'Cache Update: when no data exist in the cache'() {
given: 'a schema set exists'
def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
@@ -113,23 +105,8 @@
then: 'cached value is same as expected'
def cachedValue = getCachedValue('my-dataspace', 'my-schemaset')
cachedValue.getModuleReferences() == yangTextSchemaSourceSet.getModuleReferences()
- }
-
- def 'Cache Update: with invalid #scenario'() {
- given: 'a schema set exists'
- def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
- def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
- when: 'schema-set information is asked'
- objectUnderTest.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet)
- then: 'an data validation exception is thrown'
- thrown(DataValidationException)
- and: 'module persistence is not invoked'
- 0 * mockModuleStoreService.getYangSchemaResources(_, _)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
}
def 'Cache Evict:with invalid #scenario'() {
@@ -143,18 +120,8 @@
objectUnderTest.removeFromCache('my-dataspace', 'my-schemaset')
then: 'cached does not have value'
assert getCachedValue('my-dataspace', 'my-schemaset') == null
- }
-
- def 'Cache Evict: remove when exist'() {
- when: 'cache is evicted for schemaset'
- objectUnderTest.removeFromCache(dataspaceName, schemaSetName)
- then: 'an data validation exception is thrown'
- thrown(DataValidationException)
- where: 'the following parameters are used'
- scenario | dataspaceName | schemaSetName
- 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
- 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
- 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
}
def 'Cache Evict: remove when does not exist'() {
@@ -164,6 +131,8 @@
objectUnderTest.removeFromCache('my-dataspace', 'my-schemaset')
then: 'cached does not have value'
assert getCachedValue('my-dataspace', 'my-schemaset') == null
+ and: 'the CpsValidator is called on the dataspaceName and schemaSetName'
+ 1 * mockCpsValidator.validateNameCharacters('my-dataspace', 'my-schemaset')
}
def getCachedValue(dataSpace, schemaSet) {