From 85ad508f2c4500667fcfbc451f22032e508eedac Mon Sep 17 00:00:00 2001 From: mpriyank Date: Wed, 6 Jul 2022 21:56:47 +0100 Subject: CmHandleState Handler - State handler taking care of ADVISED, READY and LOCKED state transition at the moment. - For now I have not removed the actual code but eventually state handler will take care of persisting the state and publishing of the events - Rebased code to add the global parameter related to dataSyncCache - UPCOMING : The classes will be prefixed/renamed with LCM once we have the LcmEvent created with new schema Issue-ID: CPS-1118 Change-Id: Ic45d95169eb0c06cfb35c907d34380dbcbf2da11 Signed-off-by: mpriyank --- .../NcmpEventsCmHandleStateHandlerImplSpec.groovy | 122 +++++++++++++++++++++ .../api/impl/event/NcmpEventsServiceSpec.groovy | 38 ++----- 2 files changed, 133 insertions(+), 27 deletions(-) create mode 100644 cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy (limited to 'cps-ncmp-service/src/test/groovy/org') diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy new file mode 100644 index 000000000..f2e730d3a --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsCmHandleStateHandlerImplSpec.groovy @@ -0,0 +1,122 @@ +/* + * ============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.impl.event + +import com.fasterxml.jackson.databind.ObjectMapper +import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle +import org.onap.cps.ncmp.api.inventory.CompositeState +import org.onap.cps.ncmp.api.inventory.DataStoreSyncState +import org.onap.cps.ncmp.api.inventory.InventoryPersistence +import org.onap.cps.utils.JsonObjectMapper +import spock.lang.Specification + +import static org.onap.cps.ncmp.api.inventory.CmHandleState.ADVISED +import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED +import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY +import static org.onap.cps.ncmp.api.inventory.LockReasonCategory.LOCKED_MODULE_SYNC_FAILED + +class NcmpEventsCmHandleStateHandlerImplSpec extends Specification { + + def mockInventoryPersistence = Mock(InventoryPersistence) + def mockNcmpEventsCreator = Mock(NcmpEventsCreator) + def spiedJsonObjectMapper = Spy(new JsonObjectMapper(new ObjectMapper())) + def mockNcmpEventsService = Mock(NcmpEventsService) + + def objectUnderTest = new NcmpEventsCmHandleStateHandlerImpl(mockInventoryPersistence, mockNcmpEventsCreator, spiedJsonObjectMapper, mockNcmpEventsService) + + def 'Update and Publish Events on State Change #stateChange'() { + given: 'Cm Handle represented as YangModelCmHandle' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState(cmHandleState: fromCmHandleState) + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + when: 'update state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, toCmHandleState) + then: 'state is saved using inventory persistence' + expectedCallsToInventoryPersistence * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) + and: 'event service is called to publish event' + expectedCallsToEventService * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) + where: 'state change parameters are provided' + stateChange | fromCmHandleState | toCmHandleState || expectedCallsToInventoryPersistence | expectedCallsToEventService + 'ADVISED to READY' | ADVISED | READY || 1 | 1 + 'READY to LOCKED' | READY | LOCKED || 1 | 1 + 'ADVISED to ADVISED' | ADVISED | ADVISED || 0 | 0 + 'READY to READY' | READY | READY || 0 | 0 + 'LOCKED to LOCKED' | LOCKED | LOCKED || 0 | 0 + + } + + def 'Update and Publish Events on State Change from NO_EXISTING state to ADVISED'() { + given: 'Cm Handle represented as YangModelCmHandle in READY state' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState() + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + when: 'update state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) + then: 'state is saved using inventory persistence' + 1 * mockInventoryPersistence.saveListElements(_) + and: 'event service is called to publish event' + 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) + } + + def 'Update and Publish Events on State Change from LOCKED to ADVISED'() { + given: 'Cm Handle represented as YangModelCmHandle in LOCKED state' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState(cmHandleState: LOCKED, + lockReason: CompositeState.LockReason.builder().lockReasonCategory(LOCKED_MODULE_SYNC_FAILED).details('some lock details').build()) + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + when: 'update state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, ADVISED) + then: 'state is saved using inventory persistence and old lock reason details are retained' + 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { + args -> { + assert (args[1] as CompositeState).lockReason.details == 'some lock details' + } + } + and: 'event service is called to publish event' + 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) + } + + def 'Update and Publish Events on State Change to READY with #scenario'() { + given: 'Cm Handle represented as YangModelCmHandle' + def cmHandleId = 'cmhandle-id-1' + def compositeState = new CompositeState(cmHandleState: ADVISED) + def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, dmiProperties: [], publicProperties: [], compositeState: compositeState) + and: 'global sync flag is set' + objectUnderTest.isGlobalDataSyncCacheEnabled = dataSyncCacheEnabled + when: 'update cmhandle state is invoked' + objectUnderTest.updateCmHandleState(yangModelCmHandle, READY) + then: 'state is saved using inventory persistence with expected dataSyncState' + 1 * mockInventoryPersistence.saveCmHandleState(cmHandleId, _) >> { + args-> { + assert (args[1] as CompositeState).dataSyncEnabled == dataSyncCacheEnabled + assert (args[1] as CompositeState).dataStores.operationalDataStore.dataStoreSyncState == expectedDataStoreSyncState + + } + } + and: 'event service is called to publish event' + 1 * mockNcmpEventsService.publishNcmpEvent(cmHandleId, _) + where: + scenario | dataSyncCacheEnabled || expectedDataStoreSyncState + 'data sync cache enabled' | true || DataStoreSyncState.UNSYNCHRONIZED + 'data sync cache is not enabled' | false || DataStoreSyncState.NONE_REQUESTED + + } +} diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy index 52806a867..8bf02c11c 100644 --- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/api/impl/event/NcmpEventsServiceSpec.groovy @@ -20,46 +20,30 @@ package org.onap.cps.ncmp.api.impl.event -import org.onap.cps.ncmp.api.impl.utils.YangDataConverter -import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle -import org.onap.cps.ncmp.api.inventory.InventoryPersistence + import org.onap.ncmp.cmhandle.lcm.event.NcmpEvent import spock.lang.Specification class NcmpEventsServiceSpec extends Specification { - def mockInventoryPersistence = Mock(InventoryPersistence) def mockNcmpEventsPublisher = Mock(NcmpEventsPublisher) - def mockNcmpEventsCreator = Mock(NcmpEventsCreator) - def objectUnderTest = new NcmpEventsService(mockInventoryPersistence, mockNcmpEventsPublisher, mockNcmpEventsCreator) + def objectUnderTest = new NcmpEventsService(mockNcmpEventsPublisher) def 'Create and Publish ncmp event where events are #scenario'() { - given: 'a cm handle id and operation and responses are mocked' - mockResponses('test-cm-handle-id', 'test-topic') + given: 'a cm handle id and Ncmp Event' + def cmHandleId = 'test-cm-handle-id' + def ncmpEvent = new NcmpEvent(eventId: UUID.randomUUID().toString(), eventCorrelationId: cmHandleId) and: 'notifications enabled is #notificationsEnabled' objectUnderTest.notificationsEnabled = notificationsEnabled when: 'service is called to publish ncmp event' - objectUnderTest.publishNcmpEvent('test-cm-handle-id') - then: 'creator is called #expectedTimesMethodCalled times' - expectedTimesMethodCalled * mockNcmpEventsCreator.populateNcmpEvent('test-cm-handle-id', _) - and: 'publisher is called #expectedTimesMethodCalled times' - expectedTimesMethodCalled * mockNcmpEventsPublisher.publishEvent(*_) + objectUnderTest.publishNcmpEvent('test-cm-handle-id', ncmpEvent) + then: 'publisher is called #expectedTimesMethodCalled times' + expectedTimesMethodCalled * mockNcmpEventsPublisher.publishEvent(_, cmHandleId, ncmpEvent) where: 'the following values are used' - scenario | notificationsEnabled|| expectedTimesMethodCalled - 'enabled' | true || 1 - 'disabled' | false || 0 - } - - def mockResponses(cmHandleId, topicName) { - - def yangModelCmHandle = new YangModelCmHandle(id: cmHandleId, publicProperties: [new YangModelCmHandle.Property('publicProperty1', 'value1')], dmiProperties: []) - def ncmpEvent = new NcmpEvent(eventId: UUID.randomUUID().toString(), eventCorrelationId: cmHandleId) - def ncmpServiceCmhandle = YangDataConverter.convertYangModelCmHandleToNcmpServiceCmHandle(yangModelCmHandle) - - mockInventoryPersistence.getYangModelCmHandle(cmHandleId) >> yangModelCmHandle - mockNcmpEventsCreator.populateNcmpEvent(cmHandleId, ncmpServiceCmhandle) >> ncmpEvent - mockNcmpEventsPublisher.publishEvent(topicName, cmHandleId, ncmpEvent) >> {} + scenario | notificationsEnabled || expectedTimesMethodCalled + 'enabled' | true || 1 + 'disabled' | false || 0 } } -- cgit 1.2.3-korg