summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylanB95EST <dylan.byrne@est.tech>2022-04-04 13:09:22 +0100
committerDylanB95EST <dylan.byrne@est.tech>2022-04-08 12:51:34 +0100
commitb130fd3158c537df1ce2cb1e5a7a86c3d7e0d2a7 (patch)
tree84129ee13058d2ae9b7e79d1eaa82633ca1f95eb
parentdeac4777c1a245be1dc4c423658523b41071b110 (diff)
Refactoring/ Adding Tests for Validation
Refactored classes affected by validation Have added tests for anywhere where validation is used Have refactored the parse and sync modules validation to be validated at the public api method Issue-ID: CPS-322 Change-Id: I4989cfd03300fbdca41571d0aa2d0b96978858ba Signed-off-by: DylanB95EST <dylan.byrne@est.tech>
-rw-r--r--cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java2
-rwxr-xr-xcps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java2
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapperSpec.groovy2
-rw-r--r--cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy2
-rwxr-xr-xcps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImpl.java123
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandler.java2
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java11
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/yangmodels/YangModelCmHandle.java4
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplRegistrationSpec.groovy22
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplSpec.groovy54
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy15
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/DmiOperationsBaseSpec.groovy2
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy18
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy3
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/DmiServiceUrlBuilderSpec.groovy18
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy6
-rwxr-xr-xcps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java2
-rw-r--r--cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java10
-rwxr-xr-xcps-service/src/test/groovy/org/onap/cps/api/impl/CpsAdminServiceImplSpec.groovy90
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy160
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy87
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsQueryServiceImplSpec.groovy16
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy47
-rw-r--r--docs/admin-guide.rst18
-rwxr-xr-xdocs/release-notes.rst20
29 files changed, 633 insertions, 121 deletions
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java
index 4c8fafea5..a9ec863d5 100644
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapper.java
@@ -45,7 +45,7 @@ public interface NcmpRestInputMapper {
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
DmiPluginRegistration toDmiPluginRegistration(final RestDmiPluginRegistration restDmiPluginRegistration);
- @Mapping(source = "cmHandle", target = "cmHandleID")
+ @Mapping(source = "cmHandle", target = "cmHandleId")
@Mapping(source = "cmHandleProperties", target = "dmiProperties")
@Mapping(source = "publicCmHandleProperties", target = "publicProperties")
NcmpServiceCmHandle toNcmpServiceCmHandle(final RestInputCmHandle restInputCmHandle);
diff --git a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
index 84fcd88a9..5c1f8704d 100755
--- a/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
+++ b/cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyController.java
@@ -292,7 +292,7 @@ public class NetworkCmProxyController implements NetworkCmProxyApi {
private RestOutputCmHandle toRestOutputCmHandle(final NcmpServiceCmHandle ncmpServiceCmHandle) {
final RestOutputCmHandle restOutputCmHandle = new RestOutputCmHandle();
final CmHandlePublicProperties cmHandlePublicProperties = new CmHandlePublicProperties();
- restOutputCmHandle.setCmHandle(ncmpServiceCmHandle.getCmHandleID());
+ restOutputCmHandle.setCmHandle(ncmpServiceCmHandle.getCmHandleId());
cmHandlePublicProperties.add(ncmpServiceCmHandle.getPublicProperties());
restOutputCmHandle.setPublicCmHandleProperties(cmHandlePublicProperties);
return restOutputCmHandle;
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapperSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapperSpec.groovy
index 3d54a0b08..bb762080d 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapperSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NcmpRestInputMapperSpec.groovy
@@ -43,7 +43,7 @@ class NcmpRestInputMapperSpec extends Specification {
then: 'the result returns the correct number of cm handles'
result.createdCmHandles.size() == 1
and: 'the converted cm handle has the same id'
- result.createdCmHandles[0].cmHandleID == 'example-id'
+ result.createdCmHandles[0].cmHandleId == 'example-id'
and: '(empty) properties are converted correctly'
result.createdCmHandles[0].dmiProperties == expectedDmiProperties
result.createdCmHandles[0].publicProperties == expectedPublicProperties
diff --git a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
index efe0f3ae6..b34b0fff3 100644
--- a/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
+++ b/cps-ncmp-rest/src/test/groovy/org/onap/cps/ncmp/rest/controller/NetworkCmProxyControllerSpec.groovy
@@ -231,7 +231,7 @@ class NetworkCmProxyControllerSpec extends Specification {
def cmHandleId = 'Some-Cm-Handle'
def dmiProperties = [ prop:'some DMI property' ]
def publicProperties = [ "public prop":'some public property' ]
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleID: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties)
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: dmiProperties, publicProperties: publicProperties)
and: 'the service method is invoked with the cm handle id'
1 * mockNetworkCmProxyDataService.getNcmpServiceCmHandle('Some-Cm-Handle') >> ncmpServiceCmHandle
when: 'the cm handle details api is invoked'
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 9c3d9448e..f498e5d4f 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
@@ -188,33 +188,12 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId);
final List<YangModelCmHandle.Property> dmiProperties = yangModelCmHandle.getDmiProperties();
final List<YangModelCmHandle.Property> publicProperties = yangModelCmHandle.getPublicProperties();
- ncmpServiceCmHandle.setCmHandleID(yangModelCmHandle.getId());
+ ncmpServiceCmHandle.setCmHandleId(yangModelCmHandle.getId());
setDmiProperties(dmiProperties, ncmpServiceCmHandle);
setPublicProperties(publicProperties, ncmpServiceCmHandle);
return ncmpServiceCmHandle;
}
- private void setDmiProperties(final List<YangModelCmHandle.Property> dmiProperties,
- final NcmpServiceCmHandle ncmpServiceCmHandle) {
- final Map<String, String> dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size());
- asPropertiesMap(dmiProperties, dmiPropertiesMap);
- ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap);
- }
-
- private void setPublicProperties(final List<YangModelCmHandle.Property> publicProperties,
- final NcmpServiceCmHandle ncmpServiceCmHandle) {
- final Map<String, String> publicPropertiesMap = new LinkedHashMap<>();
- asPropertiesMap(publicProperties, publicPropertiesMap);
- ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap);
- }
-
- private void asPropertiesMap(final List<YangModelCmHandle.Property> properties,
- final Map<String, String> propertiesMap) {
- for (final YangModelCmHandle.Property property: properties) {
- propertiesMap.put(property.getName(), property.getValue());
- }
- }
-
/**
* THis method registers a cm handle and initiates modules sync.
*
@@ -223,45 +202,24 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
*/
public List<CmHandleRegistrationResponse> parseAndCreateCmHandlesInDmiRegistrationAndSyncModules(
final DmiPluginRegistration dmiPluginRegistration) {
- return dmiPluginRegistration.getCreatedCmHandles().stream()
- .map(cmHandle ->
- YangModelCmHandle.toYangModelCmHandle(
- dmiPluginRegistration.getDmiPlugin(),
- dmiPluginRegistration.getDmiDataPlugin(),
- dmiPluginRegistration.getDmiModelPlugin(), cmHandle)
- )
- .map(this::registerAndSyncNewCmHandle)
- .collect(Collectors.toList());
- }
-
- private static Object handleResponse(final ResponseEntity<?> responseEntity, final OperationEnum operation) {
- if (responseEntity.getStatusCode().is2xxSuccessful()) {
- return responseEntity.getBody();
- } else {
- final String exceptionMessage = "Unable to " + operation.toString() + " resource data.";
- throw new HttpClientRequestException(exceptionMessage, (String) responseEntity.getBody(),
- responseEntity.getStatusCodeValue());
- }
- }
-
- private CmHandleRegistrationResponse registerAndSyncNewCmHandle(final YangModelCmHandle yangModelCmHandle) {
+ List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>();
try {
- CpsValidator.validateNameCharacters(yangModelCmHandle.getId());
- final String cmHandleJsonData = String.format("{\"cm-handles\":[%s]}",
- jsonObjectMapper.asJsonString(yangModelCmHandle));
- cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
- cmHandleJsonData, NO_TIMESTAMP);
- syncModulesAndCreateAnchor(yangModelCmHandle);
- return CmHandleRegistrationResponse.createSuccessResponse(yangModelCmHandle.getId());
- } catch (final AlreadyDefinedException alreadyDefinedException) {
- return CmHandleRegistrationResponse.createFailureResponse(
- yangModelCmHandle.getId(), RegistrationError.CM_HANDLE_ALREADY_EXIST);
+ cmHandleRegistrationResponses = dmiPluginRegistration.getCreatedCmHandles().stream()
+ .map(cmHandle ->
+ YangModelCmHandle.toYangModelCmHandle(
+ dmiPluginRegistration.getDmiPlugin(),
+ dmiPluginRegistration.getDmiDataPlugin(),
+ dmiPluginRegistration.getDmiModelPlugin(), cmHandle)
+ )
+ .map(this::registerAndSyncNewCmHandle)
+ .collect(Collectors.toList());
} catch (final DataValidationException dataValidationException) {
- return CmHandleRegistrationResponse.createFailureResponse(yangModelCmHandle.getId(),
- RegistrationError.CM_HANDLE_INVALID_ID);
- } catch (final Exception exception) {
- return CmHandleRegistrationResponse.createFailureResponse(yangModelCmHandle.getId(), exception);
+ cmHandleRegistrationResponses.add(CmHandleRegistrationResponse.createFailureResponse(dmiPluginRegistration
+ .getCreatedCmHandles().stream()
+ .map(NcmpServiceCmHandle::getCmHandleId).findFirst().orElse(null),
+ RegistrationError.CM_HANDLE_INVALID_ID));
}
+ return cmHandleRegistrationResponses;
}
protected void syncModulesAndCreateAnchor(final YangModelCmHandle yangModelCmHandle) {
@@ -348,4 +306,53 @@ public class NetworkCmProxyDataServiceImpl implements NetworkCmProxyDataService
cmHandleId, resourceIdentifier, optionsParamInQuery, dataStore, requestId, topicParamInQuery);
return handleResponse(responseEntity, OperationEnum.READ);
}
+
+ private void setDmiProperties(final List<YangModelCmHandle.Property> dmiProperties,
+ final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ final Map<String, String> dmiPropertiesMap = new LinkedHashMap<>(dmiProperties.size());
+ asPropertiesMap(dmiProperties, dmiPropertiesMap);
+ ncmpServiceCmHandle.setDmiProperties(dmiPropertiesMap);
+ }
+
+ private void setPublicProperties(final List<YangModelCmHandle.Property> publicProperties,
+ final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ final Map<String, String> publicPropertiesMap = new LinkedHashMap<>();
+ asPropertiesMap(publicProperties, publicPropertiesMap);
+ ncmpServiceCmHandle.setPublicProperties(publicPropertiesMap);
+ }
+
+ private void asPropertiesMap(final List<YangModelCmHandle.Property> properties,
+ final Map<String, String> propertiesMap) {
+ for (final YangModelCmHandle.Property property: properties) {
+ propertiesMap.put(property.getName(), property.getValue());
+ }
+ }
+
+
+ private CmHandleRegistrationResponse registerAndSyncNewCmHandle(final YangModelCmHandle yangModelCmHandle) {
+ try {
+ final String cmHandleJsonData = String.format("{\"cm-handles\":[%s]}",
+ jsonObjectMapper.asJsonString(yangModelCmHandle));
+ cpsDataService.saveListElements(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, NCMP_DMI_REGISTRY_PARENT,
+ cmHandleJsonData, NO_TIMESTAMP);
+ syncModulesAndCreateAnchor(yangModelCmHandle);
+ return CmHandleRegistrationResponse.createSuccessResponse(yangModelCmHandle.getId());
+ } catch (final AlreadyDefinedException alreadyDefinedException) {
+ return CmHandleRegistrationResponse.createFailureResponse(
+ yangModelCmHandle.getId(), RegistrationError.CM_HANDLE_ALREADY_EXIST);
+ } catch (final Exception exception) {
+ return CmHandleRegistrationResponse.createFailureResponse(yangModelCmHandle.getId(), exception);
+ }
+ }
+
+ private static Object handleResponse(final ResponseEntity<?> responseEntity, final OperationEnum operation) {
+ if (responseEntity.getStatusCode().is2xxSuccessful()) {
+ return responseEntity.getBody();
+ } else {
+ final String exceptionMessage = "Unable to " + operation.toString() + " resource data.";
+ throw new HttpClientRequestException(exceptionMessage, (String) responseEntity.getBody(),
+ responseEntity.getStatusCodeValue());
+ }
+ }
+
} \ No newline at end of file
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 ff79f8724..aae2f209a 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
@@ -72,7 +72,7 @@ public class NetworkCmProxyDataServicePropertyHandler {
final Collection<NcmpServiceCmHandle> ncmpServiceCmHandles) {
final List<CmHandleRegistrationResponse> cmHandleRegistrationResponses = new ArrayList<>();
for (final NcmpServiceCmHandle ncmpServiceCmHandle : ncmpServiceCmHandles) {
- final String cmHandle = ncmpServiceCmHandle.getCmHandleID();
+ final String cmHandle = ncmpServiceCmHandle.getCmHandleId();
try {
CpsValidator.validateNameCharacters(cmHandle);
final String cmHandleXpath = String.format(CM_HANDLE_XPATH_TEMPLATE, cmHandle);
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 855e52dcd..ad85edde7 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
@@ -29,6 +29,7 @@ import org.onap.cps.ncmp.api.impl.client.DmiRestClient;
import org.onap.cps.ncmp.api.impl.config.NcmpConfiguration;
import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder;
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
+import org.onap.cps.utils.CpsValidator;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
@@ -69,6 +70,7 @@ public class DmiDataOperations extends DmiOperations {
final DataStoreEnum dataStore,
final String requestId,
final String topicParamInQuery) {
+ CpsValidator.validateNameCharacters(cmHandleId);
final YangModelCmHandle yangModelCmHandle =
yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId);
final DmiRequestBody dmiRequestBody = DmiRequestBody.builder()
@@ -77,7 +79,7 @@ public class DmiDataOperations extends DmiOperations {
.build();
dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties());
final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody);
- final var dmiResourceDataUrl = dmiServiceUrlBuilder.getDmiDatastoreUrl(
+ final String dmiResourceDataUrl = dmiServiceUrlBuilder.getDmiDatastoreUrl(
dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery,
topicParamInQuery), dmiServiceUrlBuilder.populateUriVariables(
yangModelCmHandle, cmHandleId, dataStore));
@@ -100,6 +102,7 @@ public class DmiDataOperations extends DmiOperations {
final OperationEnum operation,
final String requestData,
final String dataType) {
+ CpsValidator.validateNameCharacters(cmHandleId);
final YangModelCmHandle yangModelCmHandle =
yangModelCmHandleRetriever.getDmiServiceNamesAndProperties(cmHandleId);
final DmiRequestBody dmiRequestBody = DmiRequestBody.builder()
@@ -110,9 +113,9 @@ public class DmiDataOperations extends DmiOperations {
dmiRequestBody.asDmiProperties(yangModelCmHandle.getDmiProperties());
final String jsonBody = jsonObjectMapper.asJsonString(dmiRequestBody);
final String dmiUrl =
- dmiServiceUrlBuilder.getDmiDatastoreUrl(dmiServiceUrlBuilder.populateQueryParams(resourceId,
- null, null),
- dmiServiceUrlBuilder.populateUriVariables(yangModelCmHandle, cmHandleId, PASSTHROUGH_RUNNING));
+ dmiServiceUrlBuilder.getDmiDatastoreUrl(dmiServiceUrlBuilder.populateQueryParams(resourceId,
+ null, null),
+ dmiServiceUrlBuilder.populateUriVariables(yangModelCmHandle, cmHandleId, PASSTHROUGH_RUNNING));
return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonBody);
}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java
index 6b6bdf5be..0efe8d5b6 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetriever.java
@@ -28,6 +28,7 @@ import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle;
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle;
import org.onap.cps.spi.FetchDescendantsOption;
import org.onap.cps.spi.model.DataNode;
+import org.onap.cps.utils.CpsValidator;
import org.springframework.stereotype.Component;
/**
@@ -48,9 +49,10 @@ public class YangModelCmHandleRetriever {
* @return yang model cm handle
*/
public YangModelCmHandle getDmiServiceNamesAndProperties(final String cmHandleId) {
+ CpsValidator.validateNameCharacters(cmHandleId);
final DataNode cmHandleDataNode = getCmHandleDataNode(cmHandleId);
final NcmpServiceCmHandle ncmpServiceCmHandle = new NcmpServiceCmHandle();
- ncmpServiceCmHandle.setCmHandleID(cmHandleId);
+ ncmpServiceCmHandle.setCmHandleId(cmHandleId);
populateCmHandleProperties(cmHandleDataNode, ncmpServiceCmHandle);
return YangModelCmHandle.toYangModelCmHandle(
String.valueOf(cmHandleDataNode.getLeaves().get("dmi-service-name")),
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 b60aac951..b67910725 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
@@ -30,6 +30,7 @@ import org.apache.logging.log4j.util.TriConsumer;
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.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -70,25 +71,26 @@ public class DmiServiceUrlBuilder {
.pathSegment("{dmiBasePath}")
.pathSegment("v1")
.pathSegment("ch")
- .pathSegment("{cmHandle}");
+ .pathSegment("{cmHandleId}");
}
/**
* This method populates uri variables.
*
* @param yangModelCmHandle get dmi service name
- * @param cmHandle cm handle name for dmi registration
+ * @param cmHandleId cm handle id for dmi registration
* @return {@code String} dmi service url as string
*/
public Map<String, Object> populateUriVariables(final YangModelCmHandle yangModelCmHandle,
- final String cmHandle,
+ final String cmHandleId,
final DmiOperations.DataStoreEnum dataStore) {
+ CpsValidator.validateNameCharacters(cmHandleId);
final Map<String, Object> uriVariables = new HashMap<>();
final String dmiBasePath = dmiProperties.getDmiBasePath();
uriVariables.put("dmiServiceName",
yangModelCmHandle.resolveDmiServiceName(DATA));
uriVariables.put("dmiBasePath", dmiBasePath);
- uriVariables.put("cmHandle", cmHandle);
+ uriVariables.put("cmHandleId", cmHandleId);
uriVariables.put("dataStore", dataStore.getValue());
return uriVariables;
}
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 e46b9e3da..fd3528187 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
@@ -35,6 +35,7 @@ import lombok.NoArgsConstructor;
import lombok.Setter;
import org.onap.cps.ncmp.api.impl.operations.RequiredDmiService;
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.
@@ -75,8 +76,9 @@ public class YangModelCmHandle {
final String dmiDataServiceName,
final String dmiModelServiceName,
final NcmpServiceCmHandle ncmpServiceCmHandle) {
+ CpsValidator.validateNameCharacters(ncmpServiceCmHandle.getCmHandleId());
final YangModelCmHandle yangModelCmHandle = new YangModelCmHandle();
- yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleID());
+ yangModelCmHandle.setId(ncmpServiceCmHandle.getCmHandleId());
yangModelCmHandle.setDmiServiceName(dmiServiceName);
yangModelCmHandle.setDmiDataServiceName(dmiDataServiceName);
yangModelCmHandle.setDmiModelServiceName(dmiModelServiceName);
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
index 938127020..6811b59e0 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/models/NcmpServiceCmHandle.java
@@ -39,7 +39,7 @@ import org.springframework.validation.annotation.Validated;
@NoArgsConstructor
public class NcmpServiceCmHandle {
- private String cmHandleID;
+ private String cmHandleId;
@JsonSetter(nulls = Nulls.AS_EMPTY)
private Map<String, String> dmiProperties = Collections.emptyMap();
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
index 553ac7279..673230e74 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServiceImplModelSyncSpec.groovy
@@ -51,7 +51,7 @@ class NetworkCmProxyDataServiceImplModelSyncSpec extends Specification {
given: 'a cm handle'
def ncmpServiceCmHandle = new NcmpServiceCmHandle()
def dmiServiceName = 'some service name'
- ncmpServiceCmHandle.cmHandleID = 'cm handle id 1'
+ ncmpServiceCmHandle.cmHandleId = 'cm-handle-id-1'
def yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, '' , '', ncmpServiceCmHandle)
and: 'DMI operations returns some module references'
def moduleReferences = [ new ModuleReference(moduleName:'module1',revision:'1'),
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 cb4d5ef40..1f41c6b8c 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
@@ -51,7 +51,7 @@ import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED
class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
@Shared
- def ncmpServiceCmHandle = new NcmpServiceCmHandle()
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id')
@Shared
def cmHandlesArray = ['cmHandle001']
@@ -71,8 +71,8 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def 'DMI Registration: Create, Update & Delete operations are processed in the right order'() {
given: 'a registration with operations of all three types'
def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
- dmiRegistration.setCreatedCmHandles([new NcmpServiceCmHandle(cmHandleID: 'cmhandle-1', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
- dmiRegistration.setUpdatedCmHandles([new NcmpServiceCmHandle(cmHandleID: 'cmhandle-2', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
+ dmiRegistration.setCreatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-1', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
+ dmiRegistration.setUpdatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-2', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
dmiRegistration.setRemovedCmHandles(['cmhandle-2'])
when: 'registration is processed'
objectUnderTest.updateDmiRegistrationAndSyncModule(dmiRegistration)
@@ -88,8 +88,8 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def 'DMI Registration: Response from all operations types are in response'() {
given: 'a registration with operations of all three types'
def dmiRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
- dmiRegistration.setCreatedCmHandles([new NcmpServiceCmHandle(cmHandleID: 'cmhandle-1', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
- dmiRegistration.setUpdatedCmHandles([new NcmpServiceCmHandle(cmHandleID: 'cmhandle-2', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
+ dmiRegistration.setCreatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-1', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
+ dmiRegistration.setUpdatedCmHandles([new NcmpServiceCmHandle(cmHandleId: 'cmhandle-2', publicProperties: ['publicProp1': 'value'], dmiProperties: [:])])
dmiRegistration.setRemovedCmHandles(['cmhandle-2'])
and: 'update cm-handles can be processed successfully'
def updateResponses = [CmHandleRegistrationResponse.createSuccessResponse('cmhandle-2')]
@@ -153,7 +153,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def 'Create CM-Handle Successfully: #scenario.'() {
given: 'a registration without cm-handle properties'
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
- dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleID: 'cmhandle', dmiProperties: dmiProperties, publicProperties: publicProperties)]
+ dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleId: 'cmhandle', dmiProperties: dmiProperties, publicProperties: publicProperties)]
when: 'registration is updated'
def response = objectUnderTest.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
then: 'a successful response is received'
@@ -190,9 +190,9 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def 'Create CM-Handle Multiple Requests: All cm-handles creation requests are processed'() {
given: 'a registration with three cm-handles to be created'
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server',
- createdCmHandles: [new NcmpServiceCmHandle(cmHandleID: 'cmhandle1'),
- new NcmpServiceCmHandle(cmHandleID: 'cmhandle2'),
- new NcmpServiceCmHandle(cmHandleID: 'cmhandle3')])
+ createdCmHandles: [new NcmpServiceCmHandle(cmHandleId: 'cmhandle1'),
+ new NcmpServiceCmHandle(cmHandleId: 'cmhandle2'),
+ new NcmpServiceCmHandle(cmHandleId: 'cmhandle3')])
and: 'cm-handle creation is successful for 1st and 3rd; failed for 2nd'
mockCpsDataService.saveListElements(_, _, _, _, _) >> {} >> { throw new RuntimeException("Failed") } >> {}
when: 'registration is updated to create cm-handles'
@@ -220,7 +220,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def 'Create CM-Handle Error Handling: Registration fails: #scenario'() {
given: 'a registration without cm-handle properties'
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
- dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleID: cmHandleId)]
+ dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleId: cmHandleId)]
and: 'cm-handler registration fails: #scenario'
mockCpsDataService.saveListElements(_, _, _, _, _) >> { throw exception }
when: 'registration is updated'
@@ -247,7 +247,7 @@ class NetworkCmProxyDataServiceImplRegistrationSpec extends Specification {
def objectUnderTest = getObjectUnderTest()
and: 'a registration without cm-handle properties'
def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: 'my-server')
- dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleID: 'cmhandle')]
+ dmiPluginRegistration.createdCmHandles = [new NcmpServiceCmHandle(cmHandleId: 'cmhandle')]
and: 'cm-handler models sync fails'
objectUnderTest.syncModulesAndCreateAnchor(*_) >> { throw new RuntimeException('Model-Sync failed') }
when: 'registration is updated'
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 2d01dba52..7ddbbb21d 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
@@ -25,6 +25,7 @@ package org.onap.cps.ncmp.api.impl
import org.onap.cps.ncmp.api.impl.exception.HttpClientRequestException
import org.onap.cps.ncmp.api.impl.operations.YangModelCmHandleRetriever
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.spi.exceptions.DataValidationException
import spock.lang.Shared
import static org.onap.cps.ncmp.api.impl.operations.DmiOperations.DataStoreEnum.PASSTHROUGH_OPERATIONAL
@@ -83,6 +84,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
>> { 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 'Write resource data for pass-through running from DMI using POST "not found" response (from DMI).'() {
given: 'cpsDataService returns valid dataNode'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
@@ -124,6 +136,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
response == 'dmi-response'
}
+ def 'Get resource data for pass-through operational from DMI with invalid name.'() {\
+ when: 'get resource data operational for cm-handle is called'
+ objectUnderTest.getResourceDataOperationalForCmHandle('invalid test cm handle',
+ 'testResourceId',
+ OPTIONS_PARAM,
+ NO_TOPIC,
+ NO_REQUEST_ID)
+ then: 'A data validation Exception is thrown'
+ thrown(DataValidationException)
+ }
+
def 'Get resource data for pass-through operational from DMI with Json Processing Exception.'() {
given: 'cps data service returns valid data node'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
@@ -191,6 +214,17 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
response == '{dmi-response}'
}
+ def 'Get resource data for pass-through running from DMI with invalid name.'() {
+ when: 'get resource data operational for cm-handle is called'
+ objectUnderTest.getResourceDataPassThroughRunningForCmHandle('invalid test cm handle',
+ 'testResourceId',
+ OPTIONS_PARAM,
+ NO_TOPIC,
+ NO_REQUEST_ID)
+ then: 'A data validation Exception is thrown'
+ thrown(DataValidationException)
+ }
+
def 'Get resource data for pass-through running from DMI return NOK response.'() {
given: 'cpsDataService returns valid dataNode'
mockCpsDataService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry',
@@ -223,6 +257,15 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
1 * mockCpsModuleService.getYangResourcesModuleReferences('NFP-Operational','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 * mockCpsModuleService.getYangResourcesModuleReferences(_, _)
+ }
+
def 'Get cm handle identifiers for the given module names.'() {
when: 'execute a cm handle search for the given module names'
objectUnderTest.executeCmHandleHasAllModulesSearch(['some-module-name'])
@@ -240,12 +283,21 @@ class NetworkCmProxyDataServiceImplSpec extends Specification {
when: 'getting cm handle details for a given cm handle id from ncmp service'
def result = objectUnderTest.getNcmpServiceCmHandle('Some-Cm-Handle')
then: 'the result returns the correct data'
- result.cmHandleID == 'Some-Cm-Handle'
+ result.cmHandleId == 'Some-Cm-Handle'
result.dmiProperties ==[ Book:'Romance Novel' ]
result.publicProperties == [ "Public Book":'Public Romance Novel' ]
}
+ 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 * mockYangModelCmHandleRetriever.getDmiServiceNamesAndProperties(_)
+ }
+
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/NetworkCmProxyDataServicePropertyHandlerSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
index 7aacbda51..5eba5eecd 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyDataServicePropertyHandlerSpec.groovy
@@ -29,7 +29,6 @@ import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Registra
import static org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse.Status
import org.onap.cps.api.CpsDataService
-import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse
import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.DataNodeNotFoundException
@@ -58,7 +57,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
given: 'the CPS service return a CM handle'
mockCpsDataService.getDataNode(dataspaceName, anchorName, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> cmHandleDataNode
and: 'an update cm handle request with public properties updates'
- def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: updatedPublicProperties)]
+ def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: updatedPublicProperties)]
when: 'update data node leaves is called with the update request'
objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
then: 'the replace list method is called with correct params'
@@ -80,7 +79,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
given: 'the CPS service return a CM handle'
mockCpsDataService.getDataNode(dataspaceName, anchorName, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> cmHandleDataNode
and: 'an update cm handle request with DMI properties updates'
- def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, dmiProperties: updatedDmiProperties)]
+ def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, dmiProperties: updatedDmiProperties)]
when: 'update data node leaves is called with the update request'
objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
then: 'replace list method should is called with correct params'
@@ -104,7 +103,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def cmHandleDataNode = new DataNode(xpath: cmHandleXpath, childDataNodes: originalPropertyDataNodes)
mockCpsDataService.getDataNode(dataspaceName, anchorName, cmHandleXpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> cmHandleDataNode
and: 'an update cm handle request that removes all public properties(existing and non-existing)'
- def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: ['publicProp3': null, 'publicProp4': null])]
+ def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp3': null, 'publicProp4': null])]
when: 'update data node leaves is called with the update request'
objectUnderTest.updateCmHandleProperties(cmHandleUpdateRequest)
then: 'the replace list method is not called'
@@ -123,7 +122,7 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def '#scenario error leads to #exception when we try to update cmHandle'() {
given: 'cm handles request'
- def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: [:], dmiProperties: [:])]
+ def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: [:], dmiProperties: [:])]
and: 'data node cannot be found'
mockCpsDataService.getDataNode(*_) >> { throw exception }
when: 'update data node leaves is called using correct parameters'
@@ -146,9 +145,9 @@ class NetworkCmProxyDataServicePropertyHandlerSpec extends Specification {
def 'Multiple update operations in a single request'() {
given: 'cm handles request'
- def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:]),
- new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:]),
- new NcmpServiceCmHandle(cmHandleID: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:])]
+ def cmHandleUpdateRequest = [new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:]),
+ new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:]),
+ new NcmpServiceCmHandle(cmHandleId: cmHandleId, publicProperties: ['publicProp1': "value"], dmiProperties: [:])]
and: 'data node can be found for 1st and 3rd cm-handle but not for 2nd cm-handle'
mockCpsDataService.getDataNode(*_) >> cmHandleDataNode >> { throw new DataNodeNotFoundException('NCMP-Admin', 'ncmp-dmi-registry') } >> cmHandleDataNode
when: 'update data node leaves is called using correct parameters'
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 e6f63ce1a..563116f40 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
@@ -48,7 +48,7 @@ abstract class DmiOperationsBaseSpec extends Specification {
def yangModelCmHandle = new YangModelCmHandle()
def static dmiServiceName = 'some service name'
- def static cmHandleId = 'some cm handle'
+ def static cmHandleId = 'some-cm-handle'
def static resourceIdentifier = 'parent/child'
def mockYangModelCmHandleRetrieval(dmiProperties) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
index 593a6ec93..bc30c9c77 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/operations/YangModelCmHandleRetrieverSpec.groovy
@@ -22,6 +22,7 @@ package org.onap.cps.ncmp.api.impl.operations
import org.onap.cps.api.CpsDataService
import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle
+import org.onap.cps.spi.exceptions.DataValidationException
import spock.lang.Shared
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS
@@ -34,19 +35,19 @@ class YangModelCmHandleRetrieverSpec extends Specification {
def objectUnderTest = new YangModelCmHandleRetriever(mockCpsDataService)
- def cmHandleId = 'some cm handle'
+ def cmHandleId = 'some-cm-handle'
def leaves = ["dmi-service-name":"common service name","dmi-data-service-name":"data service name","dmi-model-service-name":"model service name"]
- def xpath = "/dmi-registry/cm-handles[@id='some cm handle']"
+ def xpath = "/dmi-registry/cm-handles[@id='some-cm-handle']"
@Shared
def childDataNodesForCmHandleWithAllProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"]),
new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
@Shared
- def childDataNodesForCmHandleWithDMIProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"])]
+ def childDataNodesForCmHandleWithDMIProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/additional-properties[@name='name1']", leaves: ["name":"name1", "value":"value1"])]
@Shared
- def childDataNodesForCmHandleWithPublicProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some cm handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
+ def childDataNodesForCmHandleWithPublicProperties = [new DataNode(xpath: "/dmi-registry/cm-handles[@id='some-cm-handle']/public-properties[@name='name2']", leaves: ["name":"name2","value":"value2"])]
def "Retrieve CmHandle using datanode with #scenario."() {
given: 'the cps data service returns a data node from the DMI registry'
@@ -69,4 +70,13 @@ class YangModelCmHandleRetrieverSpec extends Specification {
'just DMI properties' | childDataNodesForCmHandleWithDMIProperties || [new YangModelCmHandle.Property("name1", "value1")] || []
'just public properties' | childDataNodesForCmHandleWithPublicProperties || [] || [new YangModelCmHandle.Property("name2", "value2")]
}
+
+ def "Retrieve CmHandle using datanode with invalid CmHandle id."() {
+ when: 'retrieving the yang modelled cm handle with an invalid id'
+ def result = objectUnderTest.getDmiServiceNamesAndProperties('cm handle id with spaces')
+ then: 'a data validation exception is thrown'
+ thrown(DataValidationException)
+ and: 'the result is not returned'
+ result == null
+ }
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy
index 470015ec1..7bbc3d753 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/models/YangModelCmHandleSpec.groovy
@@ -31,6 +31,7 @@ class YangModelCmHandleSpec extends Specification {
def 'Creating yang model cm handle from a service api cm handle.'() {
given: 'a cm handle with properties'
def ncmpServiceCmHandle = new NcmpServiceCmHandle()
+ ncmpServiceCmHandle.cmHandleId = 'cm-handle-id01'
ncmpServiceCmHandle.dmiProperties = [myDmiProperty:'value1']
ncmpServiceCmHandle.publicProperties = [myPublicProperty:'value2']
when: 'it is converted to a yang model cm handle'
@@ -47,7 +48,7 @@ class YangModelCmHandleSpec extends Specification {
def 'Resolve DMI service name: #scenario and #requiredService service require.'() {
given: 'a yang model cm handle'
- def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new NcmpServiceCmHandle())
+ def objectUnderTest = YangModelCmHandle.toYangModelCmHandle(dmiServiceName, dmiDataServiceName, dmiModelServiceName, new NcmpServiceCmHandle(cmHandleId: 'cm-handle-id-1'))
expect:
assert objectUnderTest.resolveDmiServiceName(requiredService) == expectedService
where:
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 1615d055d..4c8dcace7 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
@@ -32,21 +32,21 @@ import spock.lang.Specification
class DmiServiceUrlBuilderSpec extends Specification {
@Shared
- YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle("dmiServiceName",
- "dmiDataServiceName", "dmiModuleServiceName", new NcmpServiceCmHandle())
+ YangModelCmHandle yangModelCmHandle = YangModelCmHandle.toYangModelCmHandle('dmiServiceName',
+ 'dmiDataServiceName', 'dmiModuleServiceName', new NcmpServiceCmHandle(cmHandleId: 'some-cm-handle-id'))
- NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties();
+ NcmpConfiguration.DmiProperties dmiProperties = new NcmpConfiguration.DmiProperties()
def objectUnderTest = new DmiServiceUrlBuilder(dmiProperties)
def 'Create the dmi service url with #scenario.'() {
given: 'uri variables'
- dmiProperties.dmiBasePath = 'dmi';
+ dmiProperties.dmiBasePath = 'dmi'
def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
- "cmHandle", PASSTHROUGH_RUNNING);
+ "cmHandle", PASSTHROUGH_RUNNING)
and: 'query params'
def uriQueries = objectUnderTest.populateQueryParams(resourceId,
- 'optionsParamInQuery', topicParamInQuery);
+ 'optionsParamInQuery', topicParamInQuery)
when: 'a dmi datastore service url is generated'
def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
then: 'service url is generated as expected'
@@ -61,12 +61,12 @@ class DmiServiceUrlBuilderSpec extends Specification {
def 'Populate dmi data store url #scenario.'() {
given: 'uri variables are created'
- dmiProperties.dmiBasePath = dmiBasePath;
+ dmiProperties.dmiBasePath = dmiBasePath
def uriVars = objectUnderTest.populateUriVariables(yangModelCmHandle,
- "cmHandle", PASSTHROUGH_RUNNING);
+ "cmHandle", PASSTHROUGH_RUNNING)
and: 'null query params'
def uriQueries = objectUnderTest.populateQueryParams(null,
- null, null);
+ null, null)
when: 'a dmi datastore service url is generated'
def dmiServiceUrl = objectUnderTest.getDmiDatastoreUrl(uriQueries, uriVars)
then: 'the created dmi service url matches the expected'
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
index f486cb76d..2de087fc2 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsAdminPersistenceServiceSpec.groovy
@@ -53,7 +53,7 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
@Sql(CLEAR_DATA)
def 'Create and retrieve a new dataspace.'() {
when: 'a new dataspace is created'
- def dataspaceName = 'some new dataspace'
+ def dataspaceName = 'some-new-dataspace'
objectUnderTest.createDataspace(dataspaceName)
then: 'that dataspace can be retrieved from the dataspace repository'
def dataspaceEntity = dataspaceRepository.findByName(dataspaceName).orElseThrow()
@@ -73,7 +73,7 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
@Sql([CLEAR_DATA, SET_DATA])
def 'Create and retrieve a new anchor.'() {
when: 'a new anchor is created'
- def newAnchorName = 'my new anchor'
+ def newAnchorName = 'my-new-anchor'
objectUnderTest.createAnchor(DATASPACE_NAME, SCHEMA_SET_NAME1, newAnchorName)
then: 'that anchor can be retrieved'
def anchor = objectUnderTest.getAnchor(DATASPACE_NAME, newAnchorName)
@@ -148,7 +148,7 @@ class CpsAdminPersistenceServiceSpec extends CpsPersistenceSpecBase {
@Sql(CLEAR_DATA)
def 'Get all anchors in unknown dataspace.'() {
when: 'attempt to get all anchors in an unknown dataspace'
- objectUnderTest.getAnchors('unknown dataspace')
+ objectUnderTest.getAnchors('unknown-dataspace')
then: 'an DataspaceNotFoundException is thrown'
thrown(DataspaceNotFoundException)
}
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 399457dd6..99358984c 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
@@ -105,10 +105,10 @@ public class CpsDataServiceImpl implements CpsDataService {
final String parentNodeXpath,
final String dataNodeUpdatesAsJson,
final OffsetDateTime observedTimestamp) {
+ CpsValidator.validateNameCharacters(dataspaceName, anchorName);
final Collection<DataNode> dataNodeUpdates =
buildDataNodes(dataspaceName, anchorName,
parentNodeXpath, dataNodeUpdatesAsJson);
- CpsValidator.validateNameCharacters(dataspaceName, anchorName);
for (final DataNode dataNodeUpdate : dataNodeUpdates) {
processDataNodeUpdate(dataspaceName, anchorName, dataNodeUpdate);
}
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 8e43227f9..db8a81f27 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
@@ -101,18 +101,18 @@ public class CpsModuleServiceImpl implements CpsModuleService {
@Override
public Collection<ModuleReference> getYangResourcesModuleReferences(final String dataspaceName,
final String anchorName) {
- CpsValidator.validateNameCharacters(dataspaceName);
+ CpsValidator.validateNameCharacters(dataspaceName, anchorName);
return cpsModulePersistenceService.getYangResourceModuleReferences(dataspaceName, anchorName);
}
- private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) {
- return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed;
- }
-
@Override
public Collection<ModuleReference> identifyNewModuleReferences(
final Collection<ModuleReference> moduleReferencesToCheck) {
return cpsModulePersistenceService.identifyNewModuleReferences(moduleReferencesToCheck);
}
+ private boolean isCascadeDeleteProhibited(final CascadeDeleteAllowed cascadeDeleteAllowed) {
+ return CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED == cascadeDeleteAllowed;
+ }
+
}
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 cbe1ebbbd..33868ccf0 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,6 +24,7 @@ package org.onap.cps.api.impl
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.model.CmHandleQueryParameters
import spock.lang.Specification
@@ -41,6 +42,15 @@ class CpsAdminServiceImplSpec extends Specification {
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(_)
+ }
+
def 'Create anchor method invokes persistence service.'() {
when: 'create anchor method is invoked'
objectUnderTest.createAnchor('someDataspace', 'someSchemaSet', 'someAnchorName')
@@ -48,6 +58,15 @@ class CpsAdminServiceImplSpec extends Specification {
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(_, _, _)
+ }
+
def 'Retrieve all anchors for dataspace.'() {
given: 'that anchor is associated with the dataspace'
def anchors = [new Anchor()]
@@ -56,6 +75,15 @@ class CpsAdminServiceImplSpec extends Specification {
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(_)
+ }
+
def 'Retrieve all anchors for schema-set.'() {
given: 'that anchor is associated with the dataspace and schemaset'
def anchors = [new Anchor()]
@@ -63,6 +91,20 @@ class CpsAdminServiceImplSpec extends Specification {
expect: 'the collection provided by persistence service is returned as result'
objectUnderTest.getAnchors('someDataspace', 'someSchemaSet') == anchors
}
+ 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'
@@ -72,6 +114,20 @@ class CpsAdminServiceImplSpec extends Specification {
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'
+ }
+
def 'Delete anchor.'() {
when: 'delete anchor is invoked'
objectUnderTest.deleteAnchor('someDataspace','someAnchor')
@@ -81,6 +137,22 @@ class CpsAdminServiceImplSpec extends Specification {
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'
+ }
+
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')]
@@ -89,6 +161,15 @@ class CpsAdminServiceImplSpec extends Specification {
}
+ 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(_, _)
+ }
+
def 'Delete dataspace.'() {
when: 'delete dataspace is invoked'
objectUnderTest.deleteDataspace('someDataspace')
@@ -105,4 +186,13 @@ class CpsAdminServiceImplSpec extends Specification {
1 * mockCpsAdminPersistenceService.queryCmHandles(cmHandleQueryParameters)
}
+ 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(_)
+ }
+
}
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 fc1293cb7..faeba8d51 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
@@ -30,6 +30,7 @@ import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.FetchDescendantsOption
import org.onap.cps.spi.exceptions.DataValidationException
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.yang.YangTextSchemaSourceSet
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
@@ -69,6 +70,22 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockNotificationService.processDataUpdatedEvent(anchor, observedTimestamp, '/', Operation.CREATE)
}
+ 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')
@@ -82,6 +99,22 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockNotificationService.processDataUpdatedEvent(anchor, observedTimestamp, '/test-tree', Operation.CREATE)
}
+ 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')
@@ -112,6 +145,20 @@ class CpsDataServiceImplSpec extends Specification {
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()
@@ -123,6 +170,20 @@ class CpsDataServiceImplSpec extends Specification {
fetchDescendantsOption << FetchDescendantsOption.values()
}
+ 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')
@@ -138,6 +199,22 @@ class CpsDataServiceImplSpec extends Specification {
'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')
@@ -167,6 +244,24 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockNotificationService.processDataUpdatedEvent(anchor, observedTimestamp, '/bookstore', Operation.UPDATE)
}
+ 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: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -183,6 +278,22 @@ class CpsDataServiceImplSpec extends Specification {
'level 2 node' | '/test-tree' | '{"branch": [{"name":"Name"}]}' || '/test-tree/branch[@name=\'Name\']'
}
+ def 'Replace data node with invalid #scenario.'() {
+ when: 'replace data method is invoked with invalid #scenario'
+ objectUnderTest.replaceNodeTree(dataspaceName, anchorName, '/', _ as String, observedTimestamp)
+ then: 'a data validation exception is thrown'
+ thrown(DataValidationException)
+ and: 'the persistence service method is not invoked'
+ 0 * mockCpsDataPersistenceService.replaceDataNodeTree(_, _,_)
+ 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')
@@ -213,6 +324,22 @@ class CpsDataServiceImplSpec extends Specification {
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')
@@ -224,6 +351,23 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockNotificationService.processDataUpdatedEvent(anchor, observedTimestamp, '/test-tree/branch', Operation.DELETE)
}
+
+ 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')
@@ -235,6 +379,22 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockNotificationService.processDataUpdatedEvent(anchor, observedTimestamp, '/data-node', Operation.DELETE)
}
+ 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')
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 bae06bb9e..95d731478 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
@@ -24,7 +24,9 @@ package org.onap.cps.api.impl
import org.onap.cps.TestUtils
import org.onap.cps.api.CpsAdminService
+import org.onap.cps.spi.CascadeDeleteAllowed
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.model.Anchor
@@ -51,6 +53,20 @@ class CpsModuleServiceImplSpec extends Specification {
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'
+ }
+
def 'Create schema set from new modules and existing modules.'() {
given: 'a list of existing modules module reference'
def moduleReferenceForExistingModule = new ModuleReference("test", "2021-10-12","test.org")
@@ -61,6 +77,20 @@ class CpsModuleServiceImplSpec extends Specification {
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'
+ }
+
def 'Create schema set from invalid resources'() {
given: 'Invalid yang resource as name-to-content map'
def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('invalid.yang')
@@ -83,6 +113,20 @@ class CpsModuleServiceImplSpec extends Specification {
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'
+ }
+
def 'Delete schema-set when cascade is allowed.'() {
given: '#numberOfAnchors anchors are associated with schemaset'
def associatedAnchors = createAnchors(numberOfAnchors)
@@ -125,6 +169,26 @@ class CpsModuleServiceImplSpec extends Specification {
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')) }
@@ -139,6 +203,15 @@ class CpsModuleServiceImplSpec extends Specification {
objectUnderTest.getYangResourceModuleReferences('someDataspaceName') == moduleReferences
}
+ 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'
@@ -148,6 +221,20 @@ class CpsModuleServiceImplSpec extends Specification {
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'
+ }
+
def 'Identifying new module references'(){
given: 'module references from cm handle'
def moduleReferencesToCheck = [new ModuleReference('some-module', 'some-revision')]
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 aa01b4401..55a252c27 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
@@ -22,6 +22,7 @@ package org.onap.cps.api.impl
import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.FetchDescendantsOption
+import org.onap.cps.spi.exceptions.DataValidationException
import spock.lang.Specification
class CpsQueryServiceImplSpec extends Specification {
@@ -45,4 +46,19 @@ class CpsQueryServiceImplSpec extends Specification {
where: 'all fetch descendants options are supported'
fetchDescendantsOption << FetchDescendantsOption.values()
}
+
+ 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/YangTextSchemaSourceSetCacheSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/YangTextSchemaSourceSetCacheSpec.groovy
index 860b7399d..06c675a25 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,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* 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.
@@ -22,6 +23,7 @@ package org.onap.cps.api.impl
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
@@ -88,6 +90,20 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
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')
@@ -99,7 +115,24 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
cachedValue.getModuleReferences() == yangTextSchemaSourceSet.getModuleReferences()
}
- def 'Cache Evict: remove when exist'() {
+ 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'
+ }
+
+ def 'Cache Evict:with invalid #scenario'() {
given: 'a schema set exists in cache'
def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
@@ -112,6 +145,18 @@ class YangTextSchemaSourceSetCacheSpec extends Specification {
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'
+ }
+
def 'Cache Evict: remove when does not exist'() {
given: 'cache is empty'
yangResourceCacheImpl.clear()
diff --git a/docs/admin-guide.rst b/docs/admin-guide.rst
index 135040faa..1bc7f4ff3 100644
--- a/docs/admin-guide.rst
+++ b/docs/admin-guide.rst
@@ -1,6 +1,6 @@
.. This work is licensed under a Creative Commons Attribution 4.0 International License.
.. http://creativecommons.org/licenses/by/4.0
-.. Copyright (C) 2021 Nordix Foundation
+.. Copyright (C) 2021-2022 Nordix Foundation
.. DO NOT CHANGE THIS LABEL FOR RELEASE NOTES - EVEN THOUGH IT GIVES A WARNING
.. _adminGuide:
@@ -191,3 +191,19 @@ Prometheus Metrics can be checked at the following endpoint
.. code::
http://<cps-component-service-name>:8081/manage/prometheus
+
+Naming Validation
+-----------------
+
+As part of the Jakarta 3.1.0 release, CPS has added validation to the names of the following components:
+
+ - Dataspace names
+ - Schema Set names
+ - Anchor names
+ - Cm-Handle identifiers
+
+The following characters along with spaces are no longer valid for naming of these components.
+
+.. code::
+
+ !"#$%&'()*+,./\:;<=>?@[]^`{|}~
diff --git a/docs/release-notes.rst b/docs/release-notes.rst
index 2fea4a21f..a584b580a 100755
--- a/docs/release-notes.rst
+++ b/docs/release-notes.rst
@@ -16,6 +16,26 @@ CPS Release Notes
.. * * * JAKARTA * * *
.. ========================
+Version: 3.1.0
+==============
++--------------------------------------+--------------------------------------------------------+
+| **CPS Project** | |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Docker images** | onap/cps-and-ncmp:3.1.0 |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Release designation** | 3.1.0 Jakarta |
+| | |
++--------------------------------------+--------------------------------------------------------+
+| **Release date** | |
+| | |
++--------------------------------------+--------------------------------------------------------+
+
+Features
+--------
+ - `CPS-322 <https://jira.onap.org/browse/CPS-322>`_ Implement additional validation for names and identifiers
+
Version: 3.0.0
==============