diff options
author | 2022-07-21 14:53:37 +0200 | |
---|---|---|
committer | 2022-08-22 14:36:00 +0200 | |
commit | 41de6d64d89b8caeddb88389cf49fb2fb9e368d4 (patch) | |
tree | 7ed9f301f582f7f9252517d1e3b4dd41775d4b01 /cps-ncmp-service/src/test/groovy/org | |
parent | a1a33160054bb9e7ffa57e18270dfa0f9a2ad77e (diff) |
Distributed datastore solution for Data Sync Watchdog
- update lombok config to handle Qualifier annotation
- update Semaphore config to use ConcurrentMap
- update SyncUtils to return a list of cm handles
- update DataSyncWatchdog and ModuleSyncWatchdog with Qualifier
- update DataSyncWatchdog to handle a list of cm handles
- Use get with xpath to check cm handle state
Issue-ID: CPS-1015
Change-Id: Icb39bd29f89e0020d49a1f8960476ffe81b12362
Signed-off-by: kissand <andras.zoltan.kiss@est.tech>
Diffstat (limited to 'cps-ncmp-service/src/test/groovy/org')
-rw-r--r-- | cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy | 7 | ||||
-rw-r--r-- | cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationSemaphoresConfigSpec.groovy | 14 | ||||
-rw-r--r-- | cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy | 18 | ||||
-rw-r--r-- | cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy) | 32 | ||||
-rw-r--r-- | cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy | 29 |
5 files changed, 48 insertions, 52 deletions
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy index 19c504902..f1294ced7 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/NetworkCmProxyCmHandlerQueryServiceSpec.groovy @@ -21,7 +21,6 @@ package org.onap.cps.ncmp.api.impl import org.onap.cps.cpspath.parser.PathParsingException -import org.onap.cps.ncmp.api.NetworkCmProxyCmHandlerQueryService import org.onap.cps.ncmp.api.inventory.InventoryPersistence import org.onap.cps.ncmp.api.inventory.CmHandleQueries import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle @@ -52,7 +51,7 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification { def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) and: 'cmHandleQueries returns a non null query result' - cmHandleQueries.getCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])] + cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [new DataNode(leaves: ['id':'some-cmhandle-id'])] and: 'CmHandleQueries returns cmHandles with the relevant query result' cmHandleQueries.combineCmHandleQueries(*_) >> ['PNFDemo1': new NcmpServiceCmHandle(cmHandleId: 'PNFDemo1'), 'PNFDemo3': new NcmpServiceCmHandle(cmHandleId: 'PNFDemo3')] when: 'the query is executed for both cm handle ids and details' @@ -70,7 +69,7 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification { def conditionProperties = createConditionProperties('cmHandleWithCpsPath', [['cpsPath' : '/some/cps/path']]) cmHandleQueryParameters.setCmHandleQueryParameters([conditionProperties]) and: 'cmHandleQueries throws a path parsing exception' - cmHandleQueries.getCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> { throw thrownException } + cmHandleQueries.queryCmHandleDataNodesByCpsPath('/some/cps/path', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> { throw thrownException } when: 'the query is executed for both cm handle ids and details' objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) objectUnderTest.queryCmHandles(cmHandleQueryParameters) @@ -134,7 +133,7 @@ class NetworkCmProxyCmHandlerQueryServiceSpec extends Specification { and: 'cmHandles are returned from the module names query' inventoryPersistence.queryAnchors(['some-module-name']) >> anchorsForModuleQuery and: 'cmHandleQueries returns a datanode result' - 2 * cmHandleQueries.getCmHandleDataNodesByCpsPath(*_) >> [someCmHandleDataNode] + 2 * cmHandleQueries.queryCmHandleDataNodesByCpsPath(*_) >> [someCmHandleDataNode] when: 'the query is executed for both cm handle ids and details' def returnedCmHandlesJustIds = objectUnderTest.queryCmHandleIds(cmHandleQueryParameters) def returnedCmHandlesWithData = objectUnderTest.queryCmHandles(cmHandleQueryParameters) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationSemaphoresConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationSemaphoresConfigSpec.groovy index fe7ed9eeb..ea84b440f 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationSemaphoresConfigSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationSemaphoresConfigSpec.groovy @@ -31,19 +31,19 @@ import spock.lang.Specification class SynchronizationSemaphoresConfigSpec extends Specification { @Autowired - private Map<String, String> moduleSyncSemaphore; + private Map<String, Boolean> moduleSyncSemaphores; @Autowired - private Map<String, String> dataSyncSemaphore; + private Map<String, Boolean> dataSyncSemaphores; def 'Embedded Sync Semaphores'() { - expect: 'system is able to create an instance of ModuleSyncSemaphore' - assert null != moduleSyncSemaphore - and: 'system is able to create an instance of DataSyncSemaphore' - assert null != dataSyncSemaphore + expect: 'system is able to create an instance of ModuleSyncSemaphores' + assert null != moduleSyncSemaphores + and: 'system is able to create an instance of DataSyncSemaphores' + assert null != dataSyncSemaphores and: 'we have 2 instances' assert Hazelcast.allHazelcastInstances.size() == 2 and: 'the names match' - assert Hazelcast.allHazelcastInstances.name == ['moduleSyncSemaphore', 'dataSyncSemaphore'] + assert Hazelcast.allHazelcastInstances.name == ['moduleSyncSemaphores', 'dataSyncSemaphores'] } } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy index 10a5d6246..ff173300a 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/CmHandleQueriesSpec.groovy @@ -92,31 +92,31 @@ class CmHandleQueriesSpec extends Specification { cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', '//state[@cm-handle-state="ADVISED"]/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> sampleDataNodes when: 'cm handles are fetched by state' - def result = objectUnderTest.getCmHandlesByState(cmHandleState) + def result = objectUnderTest.queryCmHandlesByState(cmHandleState) then: 'the returned result matches the result from the persistence service' assert result == sampleDataNodes } - def 'Get Cm Handles By State and Cm-Handle Id'() { + def 'Get Cm Handles state by Cm-Handle Id'() { given: 'a cm handle state to query' def cmHandleState = CmHandleState.READY and: 'cps data service returns a list of data nodes' - cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', - '//cm-handles[@id=\'some-cm-handle\']/state[@cm-handle-state="'+ 'READY'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes + cpsDataPersistenceService.getDataNode('NCMP-Admin', 'ncmp-dmi-registry', + '/dmi-registry/cm-handles[@id=\'some-cm-handle\']/state', OMIT_DESCENDANTS) >> new DataNode(leaves: ['cm-handle-state': 'READY']) when: 'cm handles are fetched by state and id' - def result = objectUnderTest.getCmHandlesByIdAndState('some-cm-handle', cmHandleState) + def result = objectUnderTest.getCmHandleState('some-cm-handle') then: 'the returned result is a list of data nodes returned by cps data service' - assert result == sampleDataNodes + assert result == new DataNode(leaves: ['cm-handle-state': 'READY']) } - def 'Get Cm Handles By Operational Sync State : UNSYNCHRONIZED'() { + def 'Retrieve Cm Handles By Operational Sync State : UNSYNCHRONIZED'() { given: 'a cm handle state to query' def cmHandleState = CmHandleState.READY and: 'cps data service returns a list of data nodes' cpsDataPersistenceService.queryDataNodes('NCMP-Admin', 'ncmp-dmi-registry', '//state/datastores/operational[@sync-state="'+'UNSYNCHRONIZED'+'"]/ancestor::cm-handles', OMIT_DESCENDANTS) >> sampleDataNodes when: 'cm handles are fetched by the UNSYNCHRONIZED operational sync state' - def result = objectUnderTest.getCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) + def result = objectUnderTest.queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) then: 'the returned result is a list of data nodes returned by cps data service' assert result == sampleDataNodes } @@ -130,7 +130,7 @@ class CmHandleQueriesSpec extends Specification { cpsPath + '/ancestor::cm-handles', INCLUDE_ALL_DESCENDANTS) >> Arrays.asList(cmHandleDataNode) when: 'get cm handles by cps path is invoked' - def result = objectUnderTest.getCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) + def result = objectUnderTest.queryCmHandleDataNodesByCpsPath(cpsPath, INCLUDE_ALL_DESCENDANTS) then: 'the returned result is a list of data nodes returned by cps data service' assert result.contains(cmHandleDataNode) } diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy index 650a779a4..605381970 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/DataSyncWatchdogSpec.groovy @@ -26,10 +26,11 @@ import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.InventoryPersistence import org.onap.cps.ncmp.api.inventory.DataStoreSyncState -import spock.lang.Shared import spock.lang.Specification +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.ConcurrentMap -class DataSyncSpec extends Specification { +class DataSyncWatchdogSpec extends Specification { def mockInventoryPersistence = Mock(InventoryPersistence) @@ -37,10 +38,11 @@ class DataSyncSpec extends Specification { def mockSyncUtils = Mock(SyncUtils) - @Shared + def stubbedMap = Stub(ConcurrentMap) + def jsonString = '{"stores:bookstore":{"categories":[{"code":"01"}]}}' - def objectUnderTest = new DataSyncWatchdog(mockInventoryPersistence, mockCpsDataService, mockSyncUtils) + def objectUnderTest = new DataSyncWatchdog(mockInventoryPersistence, mockCpsDataService, mockSyncUtils, stubbedMap as ConcurrentHashMap) def compositeState = getCompositeState() @@ -52,7 +54,7 @@ class DataSyncSpec extends Specification { given: 'sample resource data' def resourceData = jsonString and: 'sync utilities return a cm handle twice' - mockSyncUtils.getAnUnSynchronizedReadyCmHandle() >>> [yangModelCmHandle1, yangModelCmHandle2, null] + mockSyncUtils.getUnsynchronizedReadyCmHandles() >> [yangModelCmHandle1, yangModelCmHandle2] when: 'data sync poll is executed' objectUnderTest.executeUnSynchronizedReadyCmHandlePoll() then: 'the inventory persistence cm handle returns a composite state for the first cm handle' @@ -73,24 +75,18 @@ class DataSyncSpec extends Specification { 1 * mockInventoryPersistence.saveCmHandleState('some-cm-handle-2', compositeState) } - def 'Schedule Data Sync for Cm Handle State in READY and Operational Sync State in UNSYNCHRONIZED which return empty data from Node because #scenario'() { - given: 'a yang model cm handle' - def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', compositeState: new CompositeState(dataSyncEnabled: dataSyncEnabled)) - and: 'sync utilities returns a single cm handle' - mockSyncUtils.getAnUnSynchronizedReadyCmHandle() >>> [yangModelCmHandle, null] + def 'Schedule Data Sync for Cm Handle State in READY and Operational Sync State in UNSYNCHRONIZED which return empty data from Node'() { + given: 'cm handles in an ready state and operational sync state in unsynchronized' + and: 'sync utilities return a cm handle twice' + mockSyncUtils.getUnsynchronizedReadyCmHandles() >> [yangModelCmHandle1] when: 'data sync poll is executed' objectUnderTest.executeUnSynchronizedReadyCmHandlePoll() then: 'the inventory persistence cm handle returns a composite state for the first cm handle' - 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle') >> compositeState + 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle-1') >> compositeState and: 'the sync util returns first resource data' - 1 * mockSyncUtils.getResourceData('some-cm-handle') >> resourceData + 1 * mockSyncUtils.getResourceData('some-cm-handle-1') >> null and: 'the cm-handle data is not saved' 0 * mockCpsDataService.saveData('NFP-Operational', 'some-cm-handle-1', jsonString, _) - where: - scenario | dataSyncEnabled | resourceData - 'data sync is not enabled' | false | jsonString - 'resource data is null' | true | null - 'data sync is not enabled and resource data is null' | false | null } def createSampleYangModelCmHandle(cmHandleId) { @@ -100,7 +96,7 @@ class DataSyncSpec extends Specification { def getCompositeState() { def cmHandleState = CmHandleState.READY - def compositeState = new CompositeState(cmHandleState: cmHandleState, dataSyncEnabled: true) + def compositeState = new CompositeState(cmHandleState: cmHandleState) compositeState.setDataStores(CompositeState.DataStores.builder() .operationalDataStore(CompositeState.Operational.builder().dataStoreSyncState(DataStoreSyncState.SYNCHRONIZED) .build()).build()) diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy index fb4ca3933..52fb110b3 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy @@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import org.onap.cps.ncmp.api.impl.operations.DmiDataOperations import org.onap.cps.ncmp.api.impl.operations.DmiOperations import org.onap.cps.ncmp.api.inventory.CmHandleQueries +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle import org.onap.cps.ncmp.api.inventory.CmHandleState import org.onap.cps.ncmp.api.inventory.CompositeState import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder @@ -54,7 +55,7 @@ class SyncUtilsSpec extends Specification{ def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper()) - def objectUnderTest = new SyncUtils(mockInventoryPersistence, mockCmHandleQueries, mockDmiDataOperations, jsonObjectMapper) + def objectUnderTest = new SyncUtils(mockCmHandleQueries, mockDmiDataOperations, jsonObjectMapper) @Shared def formattedDateAndTime = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(OffsetDateTime.now()) @@ -68,7 +69,7 @@ class SyncUtilsSpec extends Specification{ def 'Get an advised Cm-Handle where ADVISED cm handle #scenario'() { given: 'the inventory persistence service returns a collection of data nodes' - mockCmHandleQueries.getCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection + mockCmHandleQueries.queryCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection and: 'we have some additional (dmi, private) properties' dataNodeAdditionalProperties.xpath = dataNode.xpath + '/additional-properties[@name="dmiProp1"]' dataNode.childDataNodes = [dataNodeAdditionalProperties] @@ -106,7 +107,7 @@ class SyncUtilsSpec extends Specification{ def 'Get all locked Cm-Handle where Lock Reason is LOCKED_MODULE_SYNC_FAILED cm handle #scenario'() { given: 'the cps (persistence service) returns a collection of data nodes' - mockCmHandleQueries.getCmHandleDataNodesByCpsPath( + mockCmHandleQueries.queryCmHandleDataNodesByCpsPath( '//lock-reason[@reason="LOCKED_MODULE_SYNC_FAILED"]', FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> [dataNode] when: 'get locked Misbehaving cm handle is called' @@ -132,21 +133,21 @@ class SyncUtilsSpec extends Specification{ } - def 'Get a Cm-Handle where Operational Sync state is UnSynchronized and Cm-handle state is READY and #scenario'() { + def 'Get a Cm-Handle where #scenario'() { given: 'the inventory persistence service returns a collection of data nodes' - mockCmHandleQueries.getCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) >> unSynchronizedDataNodes - mockCmHandleQueries.getCmHandlesByIdAndState("cm-handle-123", CmHandleState.READY) >> readyDataNodes + mockCmHandleQueries.queryCmHandlesByOperationalSyncState(DataStoreSyncState.UNSYNCHRONIZED) >> unSynchronizedDataNodes + mockCmHandleQueries.cmHandleHasState('cm-handle-123', CmHandleState.READY) >> cmHandleHasState when: 'get advised cm handles are fetched' - objectUnderTest.getAnUnSynchronizedReadyCmHandle() + def yangModelCollection = objectUnderTest.getUnsynchronizedReadyCmHandles() then: 'the returned data node collection is the correct size' - readyDataNodes.size() == expectedDataNodeSize - and: 'get yang model cm handles is invoked the correct number of times' - expectedCallsToGetYangModelCmHandle * mockInventoryPersistence.getYangModelCmHandle('cm-handle-123') + yangModelCollection.size() == expectedDataNodeSize + and: 'the result contains the correct data' + yangModelCollection.stream().map(yangModel -> yangModel.id).collect(Collectors.toSet()) == expectedYangModelCollectionIds where: 'the following scenarios are used' - scenario | unSynchronizedDataNodes | readyDataNodes || expectedCallsToGetYangModelCmHandle | expectedDataNodeSize - 'exists' | [dataNode] | [dataNode] || 1 | 1 - 'unsynchronized exist but not ready' | [dataNode] | [] || 0 | 0 - 'does not exist' | [] | [] || 0 | 0 + scenario | unSynchronizedDataNodes | cmHandleHasState || expectedDataNodeSize | expectedYangModelCollectionIds + 'a Cm-Handle unsynchronized and ready' | [dataNode] | true || 1 | ['cm-handle-123'] as Set + 'a Cm-Handle unsynchronized but not ready' | [dataNode] | false || 0 | [] as Set + 'all Cm-Handle synchronized' | [] | false || 0 | [] as Set } def 'Get resource data through DMI Operations #scenario'() { |