aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorseanbeirne <sean.beirne@est.tech>2025-02-20 11:16:11 +0000
committerseanbeirne <sean.beirne@est.tech>2025-02-27 11:35:18 +0000
commitb3dfa9ba4771b3d98bbfbdb870b8ed063d4dd2ce (patch)
treed5981045a29094f191164797b6a0d1f243c7b851
parent138cae7d9d060c0f194eccb213fa2aa4cbac7105 (diff)
Change order of CM Handle Reference lookup depending on special character
- implemented new algorithm using validator to rule out standard id / prefer alternate id - moved validator imp to cps-service (not in RI) TBC!!! - changed order of characters tested in validator to fail fast (on '=') - added Boolean variation validator method to reduce overhead and prevent logic based on exceptions - improved integration test to cover all scenarios - add performance test for alternate id look up (report only) - ensured all performance test use alternate ids it '=' - added small groovy tests to restore cps-ri code coverage to 0.31 Issue-ID: CPS-2605 Change-Id: Id9c22bb69904b7f5d376b7f8319332428435333e Signed-off-by: ToineSiebelink <toine.siebelink@est.tech> Signed-off-by: seanbeirne <sean.beirne@est.tech>
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java34
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java19
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy32
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy21
-rw-r--r--cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy32
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java17
-rw-r--r--cps-service/src/main/java/org/onap/cps/utils/CpsValidatorImpl.java (renamed from cps-ri/src/main/java/org/onap/cps/ri/utils/CpsValidatorImpl.java)20
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorImplSpec.groovy (renamed from cps-ri/src/test/groovy/org/onap/cps/ri/utils/CpsValidatorImplSpec.groovy)32
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy2
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy24
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/AlternateIdPerfTest.groovy47
-rw-r--r--integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryPerfTest.groovy8
12 files changed, 193 insertions, 95 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
index 189239ceb2..7cb1c44526 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/data/DmiDataOperations.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2024 Nordix Foundation
+ * Copyright (C) 2021-2025 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -34,7 +34,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.onap.cps.api.exceptions.CpsException;
-import org.onap.cps.api.exceptions.DataValidationException;
import org.onap.cps.ncmp.api.NcmpResponseStatus;
import org.onap.cps.ncmp.api.data.models.CmResourceAddress;
import org.onap.cps.ncmp.api.data.models.DataOperationRequest;
@@ -79,7 +78,7 @@ public class DmiDataOperations {
* This method fetches the resource data from the operational data store for a given CM handle
* identifier on the specified resource using the DMI client.
*
- * @param cmResourceAddress Target datastore, CM handle, and resource identifier.
+ * @param cmResourceAddress Target datastore, CM handle reference, and resource identifier.
* @param options Options query string.
* @param topic Topic name for triggering asynchronous responses.
* @param requestId Request ID for asynchronous responses.
@@ -94,7 +93,8 @@ public class DmiDataOperations {
final String topic,
final String requestId,
final String authorization) {
- final YangModelCmHandle yangModelCmHandle = resolveYangModelCmHandleFromCmHandleReference(cmResourceAddress);
+ final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(
+ cmResourceAddress.resolveCmHandleReferenceToId());
final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState();
validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState);
final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle);
@@ -157,22 +157,22 @@ public class DmiDataOperations {
* This method creates the resource data from pass-through running data store for given cm handle
* identifier on given resource using dmi client.
*
- * @param cmHandleId network resource identifier
- * @param resourceId resource identifier
- * @param operationType operation enum
- * @param requestData the request data
- * @param dataType data type
- * @param authorization contents of Authorization header, or null if not present
+ * @param cmHandleReference network resource identifier
+ * @param resourceId resource identifier
+ * @param operationType operation enum
+ * @param requestData the request data
+ * @param dataType data type
+ * @param authorization contents of Authorization header, or null if not present
* @return {@code ResponseEntity} response entity
*/
- public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleId,
+ public ResponseEntity<Object> writeResourceDataPassThroughRunningFromDmi(final String cmHandleReference,
final String resourceId,
final OperationType operationType,
final String requestData,
final String dataType,
final String authorization) {
final CmResourceAddress cmResourceAddress =
- new CmResourceAddress(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleId, resourceId);
+ new CmResourceAddress(PASSTHROUGH_RUNNING.getDatastoreName(), cmHandleReference, resourceId);
final YangModelCmHandle yangModelCmHandle =
getYangModelCmHandle(cmResourceAddress.resolveCmHandleReferenceToId());
@@ -281,16 +281,6 @@ public class DmiDataOperations {
}).subscribe();
}
- private YangModelCmHandle resolveYangModelCmHandleFromCmHandleReference(final CmResourceAddress cmResourceAddress) {
- String cmHandleId = cmResourceAddress.getCmHandleReference();
- try {
- return getYangModelCmHandle(cmHandleId);
- } catch (final DataValidationException ignored) {
- cmHandleId = cmResourceAddress.resolveCmHandleReferenceToId();
- return getYangModelCmHandle(cmHandleId);
- }
- }
-
private String createDmiDataOperationRequestAsJsonString(
final List<DmiDataOperation> dmiDataOperationRequestBodies) {
final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder()
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
index b97da2977a..750a5050f2 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/utils/AlternateIdMatcher.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
+ * Copyright (C) 2024-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@ import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException;
import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException;
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence;
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle;
+import org.onap.cps.utils.CpsValidator;
import org.springframework.stereotype.Service;
@Service
@@ -33,6 +34,7 @@ import org.springframework.stereotype.Service;
public class AlternateIdMatcher {
private final InventoryPersistence inventoryPersistence;
+ private final CpsValidator cpsValidator;
/**
* Get yang model cm handle that matches longest alternate id by removing elements
@@ -64,11 +66,22 @@ public class AlternateIdMatcher {
* @return cm handle id string
*/
public String getCmHandleId(final String cmHandleReference) {
+ if (cpsValidator.isValidName(cmHandleReference)) {
+ return getCmHandleIdTryingStandardIdFirst(cmHandleReference);
+ }
+ return getCmHandleIdByAlternateId(cmHandleReference);
+ }
+
+ private String getCmHandleIdByAlternateId(final String cmHandleReference) {
+ // Please note: because of cm handle id validation rules this case does NOT need to try by (standard) id
+ return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId();
+ }
+
+ private String getCmHandleIdTryingStandardIdFirst(final String cmHandleReference) {
if (inventoryPersistence.isExistingCmHandleId(cmHandleReference)) {
return cmHandleReference;
- } else {
- return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId();
}
+ return inventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference).getId();
}
private String getParentPath(final String path, final String separator) {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
index 01a08e7bb5..3dd2eabe21 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/data/DmiDataOperationsSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2021-2024 Nordix Foundation
+ * Copyright (C) 2021-2025 Nordix Foundation
* Modifications Copyright (C) 2022 Bell Canada
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,8 +22,6 @@
package org.onap.cps.ncmp.impl.data
import com.fasterxml.jackson.databind.ObjectMapper
-import org.onap.cps.api.exceptions.DataNodeNotFoundException
-import org.onap.cps.api.exceptions.DataValidationException
import org.onap.cps.events.EventsPublisher
import org.onap.cps.ncmp.api.data.models.CmResourceAddress
import org.onap.cps.ncmp.api.data.models.DataOperationRequest
@@ -86,6 +84,7 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
def 'call get resource data for #expectedDataStore from DMI without topic #scenario.'() {
given: 'a cm handle for #cmHandleId'
+ alternateIdMatcher.getCmHandleId(cmHandleId) >> cmHandleId
mockYangModelCmHandleRetrieval(dmiProperties)
and: 'a positive response from DMI service when it is called with the expected parameters'
def responseFromDmi = Mono.just(new ResponseEntity<Object>('{some-key:some-value}', HttpStatus.OK))
@@ -206,33 +205,6 @@ class DmiDataOperationsSpec extends DmiOperationsBaseSpec {
CmHandleState.ADVISED || true
}
- def 'Resolving cm handle references with cm handle id.'() {
- given: 'a resource address with a cm handle id'
- def cmResourceAddress = new CmResourceAddress('some store', 'cm-handle-id', 'some resource')
- and: 'the given cm handle id is available in the inventory'
- mockInventoryPersistence.getYangModelCmHandle('cm-handle-id') >> yangModelCmHandle
- expect: 'resolving the cm handle id returns the cm handle'
- assert objectUnderTest.resolveYangModelCmHandleFromCmHandleReference(cmResourceAddress) == yangModelCmHandle
- }
-
- def 'Resolving cm handle references with alternate id #scenario.'() {
- given: 'a resource with a alternate id'
- def cmResourceAddress = new CmResourceAddress('some store', alternateId, 'some resource')
- and: 'the alternate id cannot be found in the inventory directly and that results in an exception'
- mockInventoryPersistence.getYangModelCmHandle(alternateId) >> { throw errorThrownDuringCmHandleIdSearch }
- and: 'the alternate id can be matched to a cm handle id'
- alternateIdMatcher.getCmHandleId(alternateId) >> 'cm-handle-id'
- and: 'that cm handle id is available in the inventory'
- mockInventoryPersistence.getYangModelCmHandle('cm-handle-id') >> yangModelCmHandle
- expect: 'resolving that cm handle id returns the cm handle'
- assert objectUnderTest.resolveYangModelCmHandleFromCmHandleReference(cmResourceAddress) == yangModelCmHandle
- where: 'the following alternate ids are used'
- scenario | alternateId | errorThrownDuringCmHandleIdSearch
- 'alternate id with no special characters' | 'alternate-id' | new DataNodeNotFoundException('','')
- 'alternate id with special characters' | 'alternate#id' | new DataValidationException('','')
- }
-
-
def extractDataValue(actualDataOperationCloudEvent) {
return toTargetEvent(actualDataOperationCloudEvent, DataOperationEvent).data.responses[0]
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy
index a6d21afd30..fe7c5e3817 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/utils/AlternateIdMatcherSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
+ * Copyright (C) 2024-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
@@ -24,12 +24,20 @@ import org.onap.cps.ncmp.api.exceptions.CmHandleNotFoundException
import org.onap.cps.ncmp.exceptions.NoAlternateIdMatchFoundException
import org.onap.cps.ncmp.impl.inventory.InventoryPersistence
import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.onap.cps.utils.CpsValidatorImpl
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
+@SpringBootTest
+@ContextConfiguration(classes = [InventoryPersistence, CpsValidatorImpl])
class AlternateIdMatcherSpec extends Specification {
def mockInventoryPersistence = Mock(InventoryPersistence)
- def objectUnderTest = new AlternateIdMatcher(mockInventoryPersistence)
+
+ def mockCpsValidator = Mock(CpsValidatorImpl)
+
+ def objectUnderTest = new AlternateIdMatcher(mockInventoryPersistence, mockCpsValidator)
def setup() {
given: 'cm handle in the registry with alternate id /a/b'
@@ -72,13 +80,14 @@ class AlternateIdMatcherSpec extends Specification {
when: 'a cmHandleCmReference is passed in'
def result = objectUnderTest.getCmHandleId(cmHandleReference)
then: 'the inventory persistence service returns a cm handle (or not)'
- mockInventoryPersistence.isExistingCmHandleId(cmHandleReference) >> existingCmHandleIdResponse
+ mockCpsValidator.isValidName(cmHandleReference) >> existingCmHandleIdAndValidatorResponse
+ mockInventoryPersistence.isExistingCmHandleId(cmHandleReference) >> existingCmHandleIdAndValidatorResponse
mockInventoryPersistence.getYangModelCmHandleByAlternateId(cmHandleReference) >> alternateIdGetResponse
and: 'correct result is returned'
assert result == cmHandleReference
where: 'the following parameters are used'
- cmHandleReference | existingCmHandleIdResponse | alternateIdGetResponse
- 'ch-1' | true | ''
- 'alt-1' | false | new YangModelCmHandle(id: 'alt-1')
+ cmHandleReference | existingCmHandleIdAndValidatorResponse | alternateIdGetResponse
+ 'ch-1' | true | null
+ 'alt=1' | false | new YangModelCmHandle(id: 'alt=1')
}
}
diff --git a/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy
index 9abfdbeb33..4bf8c7ca09 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy
+++ b/cps-ri/src/test/groovy/org/onap/cps/ri/CpsModulePersistenceServiceImplSpec.groovy
@@ -1,7 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (c) 2021 Bell Canada.
- * Modifications Copyright (C) 2022-2023 Nordix Foundation
+ * Modifications Copyright (C) 2022-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
package org.onap.cps.ri
import org.hibernate.exception.ConstraintViolationException
+import org.onap.cps.ri.models.DataspaceEntity
import org.onap.cps.ri.models.SchemaSetEntity
import org.onap.cps.ri.repository.DataspaceRepository
import org.onap.cps.ri.repository.ModuleReferenceRepository
@@ -30,7 +31,6 @@ import org.onap.cps.api.exceptions.DuplicatedYangResourceException
import org.onap.cps.api.model.ModuleReference
import org.springframework.dao.DataIntegrityViolationException
import spock.lang.Specification
-
import java.sql.SQLException
/**
@@ -101,4 +101,32 @@ class CpsModulePersistenceServiceImplSpec extends Specification {
noExceptionThrown()
}
+ def 'Get yang schema resources.' () {
+ given: 'mocked methods for dataspace and schema set repositories'
+ mockDataspaceRepository.getByName('someDataspaceName') >> new DataspaceEntity()
+ mockSchemaSetRepository.getByDataspaceAndName(_,_) >> new SchemaSetEntity(yangResources: [])
+ when: 'the get yang schema resources method is called'
+ def result = objectUnderTest.getYangSchemaResources('someDataspaceName', 'someSchemaSetName')
+ then: 'an empty map is returned'
+ assert result.isEmpty()
+ }
+
+ def 'Get yang module references with just dataspace name.' () {
+ given: 'mocked method return yang resource repository'
+ mockYangResourceRepository.findAllModuleReferencesByDataspace('someDataspaceName') >> []
+ when: 'the get yang resource module reference method is called with 1 parameter'
+ def result = objectUnderTest.getYangResourceModuleReferences('someDataspaceName')
+ then: 'an empty collection is returned'
+ assert result.isEmpty()
+ }
+
+ def 'Get yang module references with dataspace name and anchor.' () {
+ given: 'mocked method return yang resource repository'
+ mockYangResourceRepository.findAllModuleReferencesByDataspaceAndAnchor('someDataspaceName', 'someAnchorName') >> []
+ when: 'the get yang resource module reference method is called with 2 parameters'
+ def result = objectUnderTest.getYangResourceModuleReferences('someDataspaceName','someAnchorName')
+ then: 'an empty collection is returned'
+ assert result.isEmpty()
+ }
+
}
diff --git a/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java b/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java
index 93f51ee58d..2244ea729b 100644
--- a/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/CpsValidator.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,21 +20,32 @@
package org.onap.cps.utils;
+import org.onap.cps.api.exceptions.DataValidationException;
import org.onap.cps.api.parameters.PaginationOption;
public interface CpsValidator {
/**
+ * Validate characters in name within cps.
+ *
+ * @param name name to be validated
+ * @return true if name is valid
+ */
+ boolean isValidName(final String name);
+
+ /**
* Validate characters in names within cps.
*
- * @param names names of data to be validated
+ * @param names names to be validated
+ * @throws DataValidationException for any name that is not valid.
*/
void validateNameCharacters(final String... names);
/**
* Validate characters in names within cps.
*
- * @param names names of data to be validated
+ * @param names names to be validated
+ * @throws DataValidationException for any name that is not valid.
*/
void validateNameCharacters(final Iterable<String> names);
diff --git a/cps-ri/src/main/java/org/onap/cps/ri/utils/CpsValidatorImpl.java b/cps-service/src/main/java/org/onap/cps/utils/CpsValidatorImpl.java
index 9e89c8aed9..e1c81bfaf5 100644
--- a/cps-ri/src/main/java/org/onap/cps/ri/utils/CpsValidatorImpl.java
+++ b/cps-service/src/main/java/org/onap/cps/utils/CpsValidatorImpl.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,24 +18,32 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ri.utils;
+package org.onap.cps.utils;
import com.google.common.collect.Lists;
import java.util.Arrays;
import java.util.Collection;
import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
import org.onap.cps.api.exceptions.DataValidationException;
import org.onap.cps.api.parameters.PaginationOption;
-import org.onap.cps.utils.CpsValidator;
import org.springframework.stereotype.Component;
-@Slf4j
@Component
@RequiredArgsConstructor
public class CpsValidatorImpl implements CpsValidator {
- private static final char[] UNSUPPORTED_NAME_CHARACTERS = "!\" #$%&'()*+,./\\:;<=>?@[]^`{|}~".toCharArray();
+ private static final char[] UNSUPPORTED_NAME_CHARACTERS = "=!\" #$%&'()*+,./\\:;<>?@[]^`{|}~".toCharArray();
+
+ @Override
+ public boolean isValidName(final String name) {
+ final Collection<Character> charactersOfName = Lists.charactersOf(name);
+ for (final char unsupportedCharacter : UNSUPPORTED_NAME_CHARACTERS) {
+ if (charactersOfName.contains(unsupportedCharacter)) {
+ return false;
+ }
+ }
+ return true;
+ }
@Override
public void validateNameCharacters(final String... names) {
diff --git a/cps-ri/src/test/groovy/org/onap/cps/ri/utils/CpsValidatorImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorImplSpec.groovy
index f7c4798772..df257c9028 100644
--- a/cps-ri/src/test/groovy/org/onap/cps/ri/utils/CpsValidatorImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/CpsValidatorImplSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2023 Nordix Foundation
+ * Copyright (C) 2022-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,11 +18,10 @@
* ============LICENSE_END=========================================================
*/
-package org.onap.cps.ri.utils
+package org.onap.cps.utils
-
-import org.onap.cps.api.parameters.PaginationOption
import org.onap.cps.api.exceptions.DataValidationException
+import org.onap.cps.api.parameters.PaginationOption
import spock.lang.Specification
class CpsValidatorImplSpec extends Specification {
@@ -60,19 +59,38 @@ class CpsValidatorImplSpec extends Specification {
def 'Validating a list of names with invalid names.'() {
given: 'a list of names with an invalid name'
- def names = ['valid-name', 'name with spaces']
+ def names = ['valid-name', 'invalid name with spaces']
when: 'a list of strings is validated'
objectUnderTest.validateNameCharacters(names)
then: 'a data validation exception is thrown'
thrown(DataValidationException)
}
- def 'Validate Pagination option with invalid page index and size.'() {
+ def 'Validate valid pagination options'() {
+ when: 'the pagination option is validated'
+ objectUnderTest.validatePaginationOption(option)
+ then: 'no exception occurs'
+ noExceptionThrown()
+ where: 'the following pagination options are used'
+ option << [null, new PaginationOption(1,2)]
+ }
+
+ def 'Validate invalid pagination.'() {
when: 'the pagination option is validated using invalid options'
objectUnderTest.validatePaginationOption(new PaginationOption(-5, -2))
then: 'a data validation exception is thrown'
def exceptionThrown = thrown(DataValidationException)
and: 'the error was encountered at the following index in #scenario'
- assert exceptionThrown.getDetails().contains("Invalid page index or size")
+ assert exceptionThrown.getDetails().contains('Invalid page index or size')
+ }
+
+
+ def 'Validation with boolean result.'() {
+ expect: 'validation returns expected boolean result'
+ assert objectUnderTest.isValidName(name) == expectedResult
+ where: 'following names are used'
+ name || expectedResult
+ 'valid-name' || true
+ 'invalid name' || false
}
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
index 693cf992ee..9b79af95ff 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/base/CpsIntegrationSpecBase.groovy
@@ -281,7 +281,7 @@ abstract class CpsIntegrationSpecBase extends Specification {
def modulePrefix = moduleNameStrategy.OVERLAPPING.equals(moduleNameStrategy) ? 'same' : moduleSetTag
def moduleReferences = (1..200).collect { "${modulePrefix}Module${it}" }
(1..numberOfCmHandles).each {
- def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: "ch-${id}", moduleSetTag: moduleSetTag, alternateId: NO_ALTERNATE_ID)
+ def ncmpServiceCmHandle = new NcmpServiceCmHandle(cmHandleId: "ch-${id}", moduleSetTag: moduleSetTag, alternateId: "alt=${id}")
cmHandles.add(ncmpServiceCmHandle)
dmiDispatcher1.moduleNamesPerCmHandleId[ncmpServiceCmHandle.cmHandleId] = moduleReferences
dmiDispatcher2.moduleNamesPerCmHandleId[ncmpServiceCmHandle.cmHandleId] = moduleReferences
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy
index 222b3c0f6f..b1b777c79f 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/ncmp/AlternateIdSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
+ * Copyright (C) 2024-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
@@ -30,16 +30,13 @@ class AlternateIdSpec extends CpsIntegrationSpecBase {
def setup() {
dmiDispatcher1.moduleNamesPerCmHandleId['ch-1'] = ['M1', 'M2']
- registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, 'alternateId')
}
- def cleanup() {
- deregisterCmHandle(DMI1_URL, 'ch-1')
- }
-
- def 'AlternateId in pass-through data operations should return OK status.'() {
- given: 'the URL for the pass-through data request'
- def url = '/ncmp/v1/ch/alternateId/data/ds/ncmp-datastore:passthrough-running'
+ def 'Pass-through data operations using #scenario as reference.'() {
+ given: 'a cm handle with an alternate id'
+ registerCmHandle(DMI1_URL, 'ch-1', NO_MODULE_SET_TAG, alternateId)
+ and: 'the URL for the pass-through data request'
+ def url = "/ncmp/v1/ch/${cmHandleReference}/data/ds/ncmp-datastore:passthrough-running"
when: 'a pass-through data request is sent to NCMP'
def response = mvc.perform(get(url)
.queryParam('resourceIdentifier', 'my-resource-id')
@@ -47,8 +44,13 @@ class AlternateIdSpec extends CpsIntegrationSpecBase {
.andReturn().response
then: 'response status is Ok'
assert response.status == HttpStatus.OK.value()
+ cleanup: 'remove the test cm handle'
+ deregisterCmHandle(DMI1_URL, 'ch-1')
+ where: 'the following ids are used'
+ scenario | alternateId | cmHandleReference
+ 'standard id' | 'dont care' | 'ch-1'
+ 'alt-id with =' | 'alt=1' | 'alt=1'
+ 'alt-id without =' | 'alt-1' | 'alt-1'
}
-
-
}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/AlternateIdPerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/AlternateIdPerfTest.groovy
new file mode 100644
index 0000000000..b9d57cf14d
--- /dev/null
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/AlternateIdPerfTest.groovy
@@ -0,0 +1,47 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 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.integration.performance.ncmp
+
+import org.onap.cps.integration.ResourceMeter
+import org.onap.cps.integration.base.CpsIntegrationSpecBase
+
+/**
+ * This test does not depend on common performance test data. Hence it just extends the integration spec base.
+ */
+class AlternateIdPerfTest extends CpsIntegrationSpecBase {
+
+ def resourceMeter = new ResourceMeter()
+
+ def 'Alternate Id Lookup Performance.'() {
+ given: 'register 1,000 cm handles (with alternative ids)'
+ registerSequenceOfCmHandlesWithManyModuleReferencesButDoNotWaitForReady(DMI1_URL, 'tagA', 1000, 1)
+ when: 'perform a 1,000 lookups by alternate id'
+ resourceMeter.start()
+ (1..1000).each {
+ networkCmProxyInventoryFacade.getNcmpServiceCmHandle("alt=${it}")
+ }
+ resourceMeter.stop()
+ then: 'record the result. Not asserted, just recorded in See https://lf-onap.atlassian.net/browse/CPS-2605'
+ println "*** CPS-2605 Execution time: ${resourceMeter.totalTimeInSeconds} ms"
+ cleanup: 'deregister test cm handles'
+ deregisterSequenceOfCmHandles(DMI1_URL, 1000, 1)
+ }
+}
diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryPerfTest.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryPerfTest.groovy
index 5389732181..dbf7e71710 100644
--- a/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryPerfTest.groovy
+++ b/integration-test/src/test/groovy/org/onap/cps/integration/performance/ncmp/CmHandleQueryPerfTest.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2023-2024 Nordix Foundation
+ * Copyright (C) 2023-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
@@ -46,7 +46,7 @@ class CmHandleQueryPerfTest extends NcmpPerfTestBase {
cpsDataService.getDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR,
'/dmi-registry/cm-handles[@id="cm-' + it + '"]', OMIT_DESCENDANTS)
objectUnderTest.queryDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR,
- '/dmi-registry/cm-handles[@alternate-id="alt-' + it + '"]', OMIT_DESCENDANTS)
+ '/dmi-registry/cm-handles[@alternate-id="alt=' + it + '"]', OMIT_DESCENDANTS)
}
resourceMeter.stop()
then: 'resource usage is as expected'
@@ -100,7 +100,7 @@ class CmHandleQueryPerfTest extends NcmpPerfTestBase {
resourceMeter.start()
(1..100).each {
count += cpsQueryService.queryDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR,
- '/dmi-registry/cm-handles[@alternate-id="alt-' + it + '"]', OMIT_DESCENDANTS).size()
+ '/dmi-registry/cm-handles[@alternate-id="alt=' + it + '"]', OMIT_DESCENDANTS).size()
}
resourceMeter.stop()
then:
@@ -116,7 +116,7 @@ class CmHandleQueryPerfTest extends NcmpPerfTestBase {
def 'A batch of CM-handles is looked up by alternate-id.'() {
given: 'a CPS Path Query to look up 100 alternate-ids in a single operation'
- def cpsPathQuery = '/dmi-registry/cm-handles[' + (1..100).collect { "@alternate-id='alt-${it}'" }.join(' or ') + ']'
+ def cpsPathQuery = '/dmi-registry/cm-handles[' + (1..100).collect { "@alternate-id='alt=${it}'" }.join(' or ') + ']'
when: 'CM-handles are looked up by alternate-ids in a single query'
resourceMeter.start()
def count = cpsQueryService.queryDataNodes(NCMP_PERFORMANCE_TEST_DATASPACE, REGISTRY_ANCHOR, cpsPathQuery, OMIT_DESCENDANTS).size()