summaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src/test/groovy/org
diff options
context:
space:
mode:
authorToineSiebelink <toine.siebelink@est.tech>2022-08-29 12:35:33 +0100
committerToineSiebelink <toine.siebelink@est.tech>2022-08-29 12:35:33 +0100
commit6b2cdc63c02cc2d1a9bc9d43997ab14e740d7973 (patch)
tree68bb0534bf74db93d8c0756ec210c0efa502eb91 /cps-ncmp-service/src/test/groovy/org
parente2a699f90d9b755230ea960df21abef55bc305ce (diff)
Performance Improvement: Use hazelcast blocking queue
- Introducing hazelcast for queue and progress map - process batch of 100 at the time - decreased module sync watchdog sleeptime to 5 seconds - separate module sync tasks in new class and some other async preparations and easier testing - tests for batching in module sync watchdog - remove qualifiers annotation (support) where no longer needed Issue-ID: CPS-1210 Issue-ID: CPS-1126 Signed-off-by: ToineSiebelink <toine.siebelink@est.tech> Change-Id: I0a7d3755bf774e27c5688741bddb01f427d4a8a7
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/config/embeddedcache/SynchronizationCacheConfigSpec.groovy (renamed from cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/config/embeddedcache/SynchronizationSemaphoresConfigSpec.groovy)33
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy34
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy110
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy112
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/SyncUtilsSpec.groovy16
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/YangDataConverterSpec.groovy42
6 files changed, 216 insertions, 131 deletions
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/SynchronizationCacheConfigSpec.groovy
index ea84b440f..80aa81b04 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/SynchronizationCacheConfigSpec.groovy
@@ -17,33 +17,38 @@
* SPDX-License-Identifier: Apache-2.0
* ============LICENSE_END=========================================================
*/
-
package org.onap.cps.ncmp.api.impl.config.embeddedcache
-
import com.hazelcast.core.Hazelcast
+import org.onap.cps.spi.model.DataNode
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ContextConfiguration
import spock.lang.Specification
+import java.util.concurrent.BlockingQueue
@SpringBootTest
-@ContextConfiguration(classes = [SynchronizationSemaphoresConfig])
-class SynchronizationSemaphoresConfigSpec extends Specification {
+@ContextConfiguration(classes = [SynchronizationCacheConfig])
+class SynchronizationCacheConfigSpec extends Specification {
+
+ @Autowired
+ private BlockingQueue<DataNode> moduleSyncWorkQueue
@Autowired
- private Map<String, Boolean> moduleSyncSemaphores;
+ private Map<String, Object> moduleSyncStartedOnCmHandles
@Autowired
- private Map<String, Boolean> dataSyncSemaphores;
+ private Map<String, Boolean> dataSyncSemaphores
- def 'Embedded Sync Semaphores'() {
- expect: 'system is able to create an instance of ModuleSyncSemaphores'
- assert null != moduleSyncSemaphores
- and: 'system is able to create an instance of DataSyncSemaphores'
+ def 'Embedded (hazelcast) Caches for Module and Data Sync.'() {
+ expect: 'system is able to create an instance of the Module Sync Work Queue'
+ assert null != moduleSyncWorkQueue
+ and: 'system is able to create an instance of a map to hold cm handles which have started (and maybe finished) module sync'
+ assert null != moduleSyncStartedOnCmHandles
+ and: 'system is able to create an instance of a map to hold data sync semaphores'
assert null != dataSyncSemaphores
- and: 'we have 2 instances'
- assert Hazelcast.allHazelcastInstances.size() == 2
- and: 'the names match'
- assert Hazelcast.allHazelcastInstances.name == ['moduleSyncSemaphores', 'dataSyncSemaphores']
+ and: 'there 3 instances'
+ assert Hazelcast.allHazelcastInstances.size() == 3
+ and: 'they have the correct names (in any order)'
+ assert Hazelcast.allHazelcastInstances.name.containsAll('moduleSyncWorkQueue', 'moduleSyncStartedOnCmHandles', 'dataSyncSemaphores' )
}
}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy
index 6a2fbe8e7..78da7eb74 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncServiceSpec.groovy
@@ -24,8 +24,6 @@ import org.onap.cps.api.CpsAdminService
import org.onap.cps.api.CpsModuleService
import org.onap.cps.ncmp.api.impl.operations.DmiModelOperations
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.models.NcmpServiceCmHandle
import org.onap.cps.spi.CascadeDeleteAllowed
import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
@@ -34,7 +32,6 @@ import spock.lang.Specification
class ModuleSyncServiceSpec extends Specification {
-
def mockCpsModuleService = Mock(CpsModuleService)
def mockDmiModelOperations = Mock(DmiModelOperations)
def mockCpsAdminService = Mock(CpsAdminService)
@@ -72,38 +69,27 @@ class ModuleSyncServiceSpec extends Specification {
}
def 'Delete Schema Set for CmHandle' () {
- given: 'a CmHandle in the advised state'
- def cmHandle = new YangModelCmHandle(id: 'some-cmhandle-id', compositeState: new CompositeState(cmHandleState: CmHandleState.ADVISED))
- and: 'the Schema Set exists for the CmHandle'
- 1 * mockCpsModuleService.deleteSchemaSet(_ as String, 'some-cmhandle-id',
- CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
when: 'delete schema set if exists is called'
- objectUnderTest.deleteSchemaSetIfExists(cmHandle)
- then: 'there are no exceptions'
- noExceptionThrown()
+ objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id')
+ then: 'the module service is invoked to delete the correct schema set'
+ 1 * mockCpsModuleService.deleteSchemaSet(expectedDataspaceName, 'some-cmhandle-id', CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED)
}
def 'Delete a non-existing Schema Set for CmHandle' () {
- given: 'a CmHandle in the advised state'
- def cmHandle = new YangModelCmHandle(id: 'some-cmhandle-id', compositeState: new CompositeState(cmHandleState: CmHandleState.ADVISED))
- and: 'the DB throws an exception because its Schema Set does not exist'
- 1 * mockCpsModuleService.deleteSchemaSet(_ as String, 'some-cmhandle-id',
- CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) >> { throw new SchemaSetNotFoundException('some-dataspace-name', 'some-cmhandle-id') }
+ given: 'the DB throws an exception because its Schema Set does not exist'
+ mockCpsModuleService.deleteSchemaSet(*_) >> { throw new SchemaSetNotFoundException('some-dataspace-name', 'some-cmhandle-id') }
when: 'delete schema set if exists is called'
- objectUnderTest.deleteSchemaSetIfExists(cmHandle)
- then: 'there are no exceptions'
+ objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id')
+ then: 'the exception from the DB is ignored; there are no exceptions'
noExceptionThrown()
}
def 'Delete Schema Set for CmHandle with other exception' () {
- given: 'a CmHandle in the advised state'
- def cmHandle = new YangModelCmHandle(id: 'some-cmhandle-id', compositeState: new CompositeState(cmHandleState: CmHandleState.ADVISED))
- and: 'an exception other than SchemaSetNotFoundException is thrown'
+ given: 'an exception other than SchemaSetNotFoundException is thrown'
UnsupportedOperationException unsupportedOperationException = new UnsupportedOperationException();
- 1 * mockCpsModuleService.deleteSchemaSet(_ as String, 'some-cmhandle-id',
- CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED) >> { throw unsupportedOperationException }
+ 1 * mockCpsModuleService.deleteSchemaSet(*_) >> { throw unsupportedOperationException }
when: 'delete schema set if exists is called'
- objectUnderTest.deleteSchemaSetIfExists(cmHandle)
+ objectUnderTest.deleteSchemaSetIfExists('some-cmhandle-id')
then: 'an exception is thrown'
def result = thrown(UnsupportedOperationException)
result == unsupportedOperationException
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy
new file mode 100644
index 000000000..291ba968f
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncTasksSpec.groovy
@@ -0,0 +1,110 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 Nordix Foundation
+ * Modifications Copyright (C) 2022 Bell Canada
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.inventory.sync
+
+import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsCmHandleStateHandler
+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
+import org.onap.cps.ncmp.api.inventory.InventoryPersistence
+import org.onap.cps.ncmp.api.inventory.LockReasonCategory
+import org.onap.cps.spi.model.DataNode
+import spock.lang.Specification
+
+class ModuleSyncTasksSpec extends Specification {
+
+ def mockInventoryPersistence = Mock(InventoryPersistence)
+
+ def mockSyncUtils = Mock(SyncUtils)
+
+ def mockModuleSyncService = Mock(ModuleSyncService)
+
+ def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
+
+ def objectUnderTest = new ModuleSyncTasks(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService, mockLcmEventsCmHandleStateHandler)
+
+ def 'Module Sync ADVISED cm handles.'() {
+ given: 'cm handles in an ADVISED state'
+ def cmHandle1 = advisedCmHandleAsDataNode('cm-handle-1')
+ def cmHandle2 = advisedCmHandleAsDataNode('cm-handle-2')
+ and: 'the inventory persistence cm handle returns a ADVISED state for the any handle'
+ mockInventoryPersistence.getCmHandleState(_) >> new CompositeState(cmHandleState: CmHandleState.ADVISED)
+ when: 'module sync poll is executed'
+ objectUnderTest.performModuleSync([cmHandle1, cmHandle2])
+ then: 'module sync service deletes schemas set of each cm handle if it already exists'
+ 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-1')
+ 1 * mockModuleSyncService.deleteSchemaSetIfExists('cm-handle-2')
+ and: 'module sync service is invoked for each cm handle'
+ 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args,'cm-handle-1') }
+ 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(_) >> { args -> assertYamgModelCmHandleArgument(args,'cm-handle-2') }
+ and: 'the state handler is called for the both cm handles'
+ 2 * mockLcmEventsCmHandleStateHandler.updateCmHandleState(_, CmHandleState.READY)
+ }
+
+ def 'Module Sync ADVISED cm handle with failure during sync.'() {
+ given: 'a cm handle in an ADVISED state'
+ def cmHandle = advisedCmHandleAsDataNode('cm-handle')
+ and: 'the inventory persistence cm handle returns a ADVISED state for the cm handle'
+ def cmHandleState = new CompositeState(cmHandleState: CmHandleState.ADVISED)
+ 1 * mockInventoryPersistence.getCmHandleState('cm-handle') >> cmHandleState
+ and: 'module sync service attempts to sync the cm handle and throws an exception'
+ 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(*_) >> { throw new Exception('some exception') }
+ when: 'module sync is executed'
+ objectUnderTest.performModuleSync([cmHandle])
+ then: 'update lock reason, details and attempts is invoked'
+ 1 * mockSyncUtils.updateLockReasonDetailsAndAttempts(cmHandleState, LockReasonCategory.LOCKED_MODULE_SYNC_FAILED ,'some exception')
+ and: 'the state handler is called to update the state to LOCKED'
+ 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleState(_, CmHandleState.LOCKED)
+ }
+
+ def 'Reset failed CM Handles #scenario.'() {
+ given: 'cm handles in an locked state'
+ def lockedState = new CompositeStateBuilder().withCmHandleState(CmHandleState.LOCKED)
+ .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, '').withLastUpdatedTimeNow().build()
+ def yangModelCmHandle1 = new YangModelCmHandle(id: 'cm-handle-1', compositeState: lockedState)
+ def yangModelCmHandle2 = new YangModelCmHandle(id: 'cm-handle-2', compositeState: lockedState)
+ and: 'sync utils retry locked cm handle returns #isReadyForRetry'
+ mockSyncUtils.isReadyForRetry(lockedState) >>> isReadyForRetry
+ when: 'resetting failed cm handles'
+ objectUnderTest.resetFailedCmHandles([yangModelCmHandle1, yangModelCmHandle2])
+ then: 'updated to state "ADVISED" from "READY" is called as often as there are cm handles ready for retry'
+ expectedNumberOfInvocationsToSaveCmHandleState * mockLcmEventsCmHandleStateHandler.updateCmHandleState(_, CmHandleState.ADVISED)
+ where:
+ scenario | isReadyForRetry || expectedNumberOfInvocationsToSaveCmHandleState
+ 'retry locked cm handle once' | [true, false] || 1
+ 'retry locked cm handle twice' | [true, true] || 2
+ 'do not retry locked cm handle' | [false, false] || 0
+ }
+
+ def advisedCmHandleAsDataNode(cmHandleId) {
+ return new DataNode(anchorName:cmHandleId, leaves:['id':cmHandleId, 'cm-handle-state':'ADVISED'])
+ }
+
+ def assertYamgModelCmHandleArgument(args, expectedCmHandleId) {
+ {
+ def yangModelCmHandle = args[0]
+ assert yangModelCmHandle.id == expectedCmHandleId
+ }
+ return true
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy
index 81268cbc0..43f492dbd 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/inventory/sync/ModuleSyncWatchdogSpec.groovy
@@ -21,98 +21,56 @@
package org.onap.cps.ncmp.api.inventory.sync
-
-import org.onap.cps.ncmp.api.impl.event.lcm.LcmEventsCmHandleStateHandler
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.InventoryPersistence
-import org.onap.cps.ncmp.api.inventory.LockReasonCategory
-import org.onap.cps.ncmp.api.inventory.CompositeStateBuilder
-import spock.lang.Specification
-import java.util.concurrent.ConcurrentHashMap
-import java.util.concurrent.ConcurrentMap
+import java.util.concurrent.ArrayBlockingQueue
+import java.util.concurrent.BlockingQueue
+import org.onap.cps.spi.model.DataNode
+import spock.lang.Specification
class ModuleSyncWatchdogSpec extends Specification {
- def mockInventoryPersistence = Mock(InventoryPersistence)
-
def mockSyncUtils = Mock(SyncUtils)
- def mockModuleSyncService = Mock(ModuleSyncService)
+ def static testQueueCapacity = 50 + 2 * ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE
- def stubbedMap = Stub(ConcurrentMap)
+ BlockingQueue<DataNode> moduleSyncWorkQueue = new ArrayBlockingQueue(testQueueCapacity)
- def mockLcmEventsCmHandleStateHandler = Mock(LcmEventsCmHandleStateHandler)
+ def moduleSyncStartedOnCmHandles = [:]
- def cmHandleState = CmHandleState.ADVISED
+ def mockModuleSyncTasks = Mock(ModuleSyncTasks)
- def objectUnderTest = new ModuleSyncWatchdog(mockInventoryPersistence, mockSyncUtils, mockModuleSyncService, stubbedMap as ConcurrentHashMap, mockLcmEventsCmHandleStateHandler)
+ def objectUnderTest = new ModuleSyncWatchdog(mockSyncUtils, moduleSyncWorkQueue , moduleSyncStartedOnCmHandles, mockModuleSyncTasks)
- def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handles'() {
- given: 'cm handles in an advised state and a data sync state'
- def compositeState1 = new CompositeState(cmHandleState: cmHandleState)
- def compositeState2 = new CompositeState(cmHandleState: cmHandleState)
- def yangModelCmHandle1 = new YangModelCmHandle(id: 'some-cm-handle', compositeState: compositeState1)
- def yangModelCmHandle2 = new YangModelCmHandle(id: 'some-cm-handle-2', compositeState: compositeState2)
- and: 'sync utilities return a cm handle twice'
- mockSyncUtils.getAdvisedCmHandles() >> [yangModelCmHandle1, yangModelCmHandle2]
- when: 'module sync poll is executed'
- objectUnderTest.executeAdvisedCmHandlePoll()
- then: 'the inventory persistence cm handle returns a composite state for the first cm handle'
- 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle') >> compositeState1
- and: 'module sync service deletes schema set of cm handle if it exists'
- 1 * mockModuleSyncService.deleteSchemaSetIfExists(yangModelCmHandle1)
- and: 'module sync service syncs the first cm handle and creates a schema set'
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle1)
- then: 'the state handler is called for the first cm handle'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleState(yangModelCmHandle1, CmHandleState.READY)
- and: 'the inventory persistence cm handle returns a composite state for the second cm handle'
- mockInventoryPersistence.getCmHandleState('some-cm-handle-2') >> compositeState2
- and: 'module sync service syncs the second cm handle and creates a schema set'
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(yangModelCmHandle2)
- then: 'the state handler is called for the second cm handle'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleState(yangModelCmHandle2, CmHandleState.READY)
+ def 'Module sync #scenario , #numberOfAdvisedCmHandles advised cm handles.'() {
+ given: 'sync utilities returns #numberOfAdvisedCmHandles advised cm handles'
+ mockSyncUtils.getAdvisedCmHandles() >> createDataNodes(numberOfAdvisedCmHandles)
+ when: ' module sync is started'
+ objectUnderTest.moduleSyncAdvisedCmHandles()
+ then: 'it performs #expectedNumberOfTaskExecutions tasks'
+ expectedNumberOfTaskExecutions * mockModuleSyncTasks.performModuleSync(_)
+ where:
+ scenario | numberOfAdvisedCmHandles || expectedNumberOfTaskExecutions
+ 'less then 1 batch' | 1 || 1
+ 'exactly 1 batch' | ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE || 1
+ '2 batches' | 2 * ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE || 2
+ 'queue capacity' | testQueueCapacity || 3
+ 'over queue capacity' | testQueueCapacity + 2 * ModuleSyncWatchdog.MODULE_SYNC_BATCH_SIZE || 3
}
- def 'Schedule a Cm-Handle Sync for ADVISED Cm-Handle with failure'() {
- given: 'cm handles in an advised state'
- def compositeState = new CompositeState(cmHandleState: cmHandleState)
- def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', compositeState: compositeState)
- and: 'sync utilities return a cm handle'
- mockSyncUtils.getAdvisedCmHandles() >> [yangModelCmHandle]
- when: 'module sync poll is executed'
- objectUnderTest.executeAdvisedCmHandlePoll()
- then: 'the inventory persistence cm handle returns a composite state for the cm handle'
- 1 * mockInventoryPersistence.getCmHandleState('some-cm-handle') >> compositeState
- and: 'module sync service attempts to sync the cm handle and throws an exception'
- 1 * mockModuleSyncService.syncAndCreateSchemaSetAndAnchor(*_) >> { throw new Exception('some exception') }
- and: 'update lock reason, details and attempts is invoked'
- 1 * mockSyncUtils.updateLockReasonDetailsAndAttempts(compositeState, LockReasonCategory.LOCKED_MODULE_SYNC_FAILED ,'some exception')
- and: 'the state handler is called to update the state to LOCKED'
- 1 * mockLcmEventsCmHandleStateHandler.updateCmHandleState(yangModelCmHandle, CmHandleState.LOCKED)
+ def 'Reset failed cm handles.'() {
+ given: 'sync utilities returns failed cm handles'
+ def failedCmHandles = [new YangModelCmHandle()]
+ mockSyncUtils.getModuleSyncFailedCmHandles() >> failedCmHandles
+ when: ' reset failed cm handles is started'
+ objectUnderTest.resetPreviouslyFailedCmHandles()
+ then: 'it is delegated to the module sync task (service)'
+ 1 * mockModuleSyncTasks.resetFailedCmHandles(failedCmHandles)
}
- def 'Schedule a Cm-Handle Sync with condition #scenario '() {
- given: 'cm handles in an locked state'
- def compositeState = new CompositeStateBuilder().withCmHandleState(CmHandleState.LOCKED)
- .withLockReason(LockReasonCategory.LOCKED_MODULE_SYNC_FAILED, '').withLastUpdatedTimeNow().build()
- def yangModelCmHandle = new YangModelCmHandle(id: 'some-cm-handle', compositeState: compositeState)
- and: 'sync utilities return a cm handle twice'
- mockSyncUtils.getModuleSyncFailedCmHandles() >> [yangModelCmHandle, yangModelCmHandle]
- and: 'inventory persistence returns the composite state of the cm handle'
- mockInventoryPersistence.getCmHandleState(yangModelCmHandle.getId()) >> compositeState
- and: 'sync utils retry locked cm handle returns #isReadyForRetry'
- mockSyncUtils.isReadyForRetry(compositeState) >>> isReadyForRetry
- when: 'module sync poll is executed'
- objectUnderTest.executeLockedCmHandlePoll()
- then: 'the first cm handle is updated to state "ADVISED" from "READY"'
- expectedNumberOfInvocationsToSaveCmHandleState * mockLcmEventsCmHandleStateHandler.updateCmHandleState(yangModelCmHandle, CmHandleState.ADVISED)
- where:
- scenario | isReadyForRetry || expectedNumberOfInvocationsToSaveCmHandleState
- 'retry locked cm handle once' | [true, false] || 1
- 'retry locked cm handle twice' | [true, true] || 2
- 'do not retry locked cm handle' | [false, false] || 0
+ def createDataNodes(numberOfDataNodes) {
+ def dataNodes = []
+ (1..numberOfDataNodes).each {dataNodes.add(new DataNode())}
+ return dataNodes
}
}
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 52fb110b3..6ccdcf12d 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
@@ -47,8 +47,6 @@ import java.util.stream.Collectors
class SyncUtilsSpec extends Specification{
- def mockInventoryPersistence = Mock(InventoryPersistence)
-
def mockCmHandleQueries = Mock(CmHandleQueries)
def mockDmiDataOperations = Mock(DmiDataOperations)
@@ -63,28 +61,14 @@ class SyncUtilsSpec extends Specification{
@Shared
def dataNode = new DataNode(leaves: ['id': 'cm-handle-123'])
- @Shared
- def dataNodeAdditionalProperties = new DataNode(leaves: ['name': 'dmiProp1', 'value': 'dmiValue1'])
-
def 'Get an advised Cm-Handle where ADVISED cm handle #scenario'() {
given: 'the inventory persistence service returns a collection of data nodes'
mockCmHandleQueries.queryCmHandlesByState(CmHandleState.ADVISED) >> dataNodeCollection
- and: 'we have some additional (dmi, private) properties'
- dataNodeAdditionalProperties.xpath = dataNode.xpath + '/additional-properties[@name="dmiProp1"]'
- dataNode.childDataNodes = [dataNodeAdditionalProperties]
when: 'get advised cm handles are fetched'
def yangModelCmHandles = objectUnderTest.getAdvisedCmHandles()
then: 'the returned data node collection is the correct size'
yangModelCmHandles.size() == expectedDataNodeSize
- and: 'if there is a data node the additional (dmi, private) properties are included'
- if (expectedDataNodeSize > 0) {
- assert yangModelCmHandles[0].dmiProperties[0].name == 'dmiProp1'
- assert yangModelCmHandles[0].dmiProperties[0].value == 'dmiValue1'
- }
- and: 'yang model collection contains the correct data'
- yangModelCmHandles.stream().map(yangModel -> yangModel.id).collect(Collectors.toSet()) ==
- dataNodeCollection.stream().map(dataNode -> dataNode.leaves.get("id")).collect(Collectors.toSet())
where: 'the following scenarios are used'
scenario | dataNodeCollection || expectedCallsToGetYangModelCmHandle | expectedDataNodeSize
'exists' | [dataNode] || 1 | 1
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/YangDataConverterSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/YangDataConverterSpec.groovy
new file mode 100644
index 000000000..20d384fa5
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/utils/YangDataConverterSpec.groovy
@@ -0,0 +1,42 @@
+/*
+ * ============LICENSE_START========================================================
+ * Copyright (C) 2022 Nordix Foundation
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.cps.ncmp.api.utils
+
+import org.onap.cps.ncmp.api.impl.utils.YangDataConverter
+import org.onap.cps.spi.model.DataNode
+import spock.lang.Specification
+
+class YangDataConverterSpec extends Specification{
+
+ def 'Convert a cm handle data node with private properties.'() {
+ given: 'a datanode with some additional (dmi, private) properties'
+ def dataNodeAdditionalProperties = new DataNode(xpath:'/additional-properties[@name="dmiProp1"]',
+ leaves: ['name': 'dmiProp1', 'value': 'dmiValue1'])
+ def dataNode = new DataNode(childDataNodes:[dataNodeAdditionalProperties])
+ when: 'the dataNode is converted'
+ def yangModelCmHandle = YangDataConverter.convertCmHandleToYangModel(dataNode,'sample-id')
+ then: 'the converted object has the correct id'
+ assert yangModelCmHandle.id == 'sample-id'
+ and: 'the additional (dmi, private) properties are included'
+ assert yangModelCmHandle.dmiProperties[0].name == 'dmiProp1'
+ assert yangModelCmHandle.dmiProperties[0].value == 'dmiValue1'
+ }
+}