diff options
author | 2024-11-27 14:43:28 +0000 | |
---|---|---|
committer | 2024-12-19 15:38:36 +0000 | |
commit | a7206655a004659bd1251c70db0acfd0f58e40d4 (patch) | |
tree | 852a2331753c722e46c03ac6b508a14b646f24e1 /cps-ncmp-service/src/test/groovy/org | |
parent | 40578d56733247540a09b6bbf000181b46b5c1fc (diff) |
Cps and Ncmp distributed lock for various use cases
- introduced cpsAndNcmpLock to be used for any use case needing
coordination. Since it can be used for any use case hence placing the
class accordingly.
- currently lock is being used for populating workQueue.
- Removed FencedLock as it was part of CPSubsystem which is moved to
hazelcast-enterprise in 5.5.* version onwards.
- added info level logging statement to verify just one thread at a time
in the critical section
- Note : integration test to be part of a separate patch.
Issue-ID: CPS-2479
Change-Id: I0f33c7232786c517383e5093fda91fd9a1839021
Signed-off-by: mpriyank <priyank.maheshwari@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/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy index 4cf07e4c24..a9b88c2d3b 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/ModuleSyncWatchdogSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2022-2023 Nordix Foundation + * Copyright (C) 2022-2024 Nordix Foundation * Modifications Copyright (C) 2022 Bell Canada * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); @@ -44,11 +44,11 @@ class ModuleSyncWatchdogSpec extends Specification { def spiedAsyncTaskExecutor = Spy(AsyncTaskExecutor) - def mockWorkQueueLock = Mock(Lock) + def mockCpsAndNcmpLock = Mock(IMap<String,String>) def spiedSleeper = Spy(Sleeper) - def objectUnderTest = new ModuleSyncWatchdog(mockModuleOperationsUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor, mockWorkQueueLock, spiedSleeper) + def objectUnderTest = new ModuleSyncWatchdog(mockModuleOperationsUtils, moduleSyncWorkQueue , mockModuleSyncStartedOnCmHandles, mockModuleSyncTasks, spiedAsyncTaskExecutor, mockCpsAndNcmpLock, spiedSleeper) void setup() { spiedAsyncTaskExecutor.setupThreadPool() @@ -59,14 +59,16 @@ class ModuleSyncWatchdogSpec extends Specification { mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(numberOfAdvisedCmHandles) and: 'module sync utilities returns no failed (locked) cm handles' mockModuleOperationsUtils.getCmHandlesThatFailedModelSyncOrUpgrade() >> [] - and: 'the work queue is not locked' - mockWorkQueueLock.tryLock() >> true + and: 'the work queue can be locked' + mockCpsAndNcmpLock.tryLock('workQueueLock') >> true and: 'the executor has enough available threads' spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 3 when: ' module sync is started' objectUnderTest.moduleSyncAdvisedCmHandles() then: 'it performs #expectedNumberOfTaskExecutions tasks' expectedNumberOfTaskExecutions * spiedAsyncTaskExecutor.executeTask(*_) + and: 'the executing thread is unlocked' + 1 * mockCpsAndNcmpLock.unlock('workQueueLock') where: 'the following parameter are used' scenario | numberOfAdvisedCmHandles || expectedNumberOfTaskExecutions 'none at all' | 0 || 0 @@ -80,8 +82,8 @@ class ModuleSyncWatchdogSpec extends Specification { def 'Module sync cm handles starts with no available threads.'() { given: 'module sync utilities returns a advise cm handles' mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(1) - and: 'the work queue is not locked' - mockWorkQueueLock.tryLock() >> true + and: 'the work queue can be locked' + mockCpsAndNcmpLock.tryLock('workQueueLock') >> true and: 'the executor first has no threads but has one thread on the second attempt' spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >>> [ 0, 1 ] when: ' module sync is started' @@ -93,8 +95,8 @@ class ModuleSyncWatchdogSpec extends Specification { def 'Module sync advised cm handle already handled by other thread.'() { given: 'module sync utilities returns an advised cm handle' mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(1) - and: 'the work queue is not locked' - mockWorkQueueLock.tryLock() >> true + and: 'the work queue can be locked' + mockCpsAndNcmpLock.tryLock('workQueueLock') >> true and: 'the executor has a thread available' spiedAsyncTaskExecutor.getAsyncTaskParallelismLevel() >> 1 and: 'the semaphore cache indicates the cm handle is already being processed' @@ -131,16 +133,18 @@ class ModuleSyncWatchdogSpec extends Specification { def 'Module Sync Locking.'() { given: 'module sync utilities returns an advised cm handle' mockModuleOperationsUtils.getAdvisedCmHandleIds() >> createCmHandleIds(1) - and: 'can lock is : #canLock' - mockWorkQueueLock.tryLock() >> canLock + and: 'can be locked is : #canLock' + mockCpsAndNcmpLock.tryLock('workQueueLock') >> canLock when: 'attempt to populate the work queue' objectUnderTest.populateWorkQueueIfNeeded() then: 'the queue remains empty is #expectQueueRemainsEmpty' assert moduleSyncWorkQueue.isEmpty() == expectQueueRemainsEmpty + and: 'unlock is called only when thread is able to enter the critical section' + expectedInvocationToUnlock * mockCpsAndNcmpLock.unlock('workQueueLock') where: 'the following lock states are applied' - canLock | expectQueueRemainsEmpty - false | true - true | false + canLock || expectQueueRemainsEmpty || expectedInvocationToUnlock + false || true || 0 + true || false || 1 } def 'Sleeper gets interrupted.'() { |