2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2024 Nordix Foundation
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the 'License');
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an 'AS IS' BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
21 package org.onap.cps.integration.functional
23 import org.onap.cps.integration.base.CpsIntegrationSpecBase
24 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
25 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
26 import org.onap.cps.ncmp.api.impl.inventory.LockReasonCategory
27 import org.onap.cps.ncmp.api.models.CmHandleRegistrationResponse
28 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
29 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
30 import org.springframework.http.HttpStatus
31 import spock.util.concurrent.PollingConditions
33 import static org.springframework.test.web.client.match.MockRestRequestMatchers.anything
34 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
36 class NcmpCmHandleCreateSpec extends CpsIntegrationSpecBase {
38 NetworkCmProxyDataService objectUnderTest
40 static final MODULE_REFERENCES_RESPONSE_A = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_Response.json')
41 static final MODULE_RESOURCES_RESPONSE_A = readResourceDataFile('mock-dmi-responses/bookStoreAWithModules_M1_M2_ResourcesResponse.json')
42 static final MODULE_REFERENCES_RESPONSE_B = readResourceDataFile('mock-dmi-responses/bookStoreBWithModules_M1_M3_Response.json')
43 static final MODULE_RESOURCES_RESPONSE_B = readResourceDataFile('mock-dmi-responses/bookStoreBWithModules_M1_M3_ResourcesResponse.json')
46 objectUnderTest = networkCmProxyDataService
49 def 'CM Handle registration is successful.'() {
50 given: 'DMI will return modules when requested'
51 mockDmiResponsesForRegistration(DMI_URL, 'ch-1', MODULE_REFERENCES_RESPONSE_A, MODULE_RESOURCES_RESPONSE_A)
53 when: 'a CM-handle is registered for creation'
54 def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
55 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: [cmHandleToCreate])
56 def dmiPluginRegistrationResponse = networkCmProxyDataService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
58 then: 'registration gives successful response'
59 assert dmiPluginRegistrationResponse.createdCmHandles == [CmHandleRegistrationResponse.createSuccessResponse('ch-1')]
61 and: 'CM-handle is initially in ADVISED state'
62 assert CmHandleState.ADVISED == objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState
64 when: 'module sync runs'
65 moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
67 then: 'CM-handle goes to READY state'
68 new PollingConditions().within(3, () -> {
69 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState('ch-1').cmHandleState
72 and: 'the CM-handle has expected modules'
73 assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences('ch-1').moduleName.sort()
75 and: 'DMI received expected requests'
76 mockDmiServer.verify()
78 cleanup: 'deregister CM handle'
79 deregisterCmHandle(DMI_URL, 'ch-1')
82 def 'CM Handle goes to LOCKED state when DMI gives error during module sync.'() {
83 given: 'DMI is not available to handle requests'
84 mockDmiServer.expect(anything()).andRespond(withStatus(HttpStatus.SERVICE_UNAVAILABLE))
86 when: 'a CM-handle is registered for creation'
87 def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-1')
88 def dmiPluginRegistration = new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: [cmHandleToCreate])
89 networkCmProxyDataService.updateDmiRegistrationAndSyncModule(dmiPluginRegistration)
91 and: 'module sync runs'
92 moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
94 then: 'CM-handle goes to LOCKED state with reason MODULE_SYNC_FAILED'
95 new PollingConditions().within(3, () -> {
96 def cmHandleCompositeState = objectUnderTest.getCmHandleCompositeState('ch-1')
97 assert cmHandleCompositeState.cmHandleState == CmHandleState.LOCKED
98 assert cmHandleCompositeState.lockReason.lockReasonCategory == LockReasonCategory.MODULE_SYNC_FAILED
101 and: 'CM-handle has no modules'
102 assert objectUnderTest.getYangResourcesModuleReferences('ch-1').empty
104 cleanup: 'deregister CM handle'
105 deregisterCmHandle(DMI_URL, 'ch-1')
108 def 'Create a CM-handle with existing moduleSetTag.'() {
109 given: 'existing CM-handles cm-1 with moduleSetTag "A", and cm-2 with moduleSetTag "B"'
110 registerCmHandle(DMI_URL, 'ch-1', 'A', MODULE_REFERENCES_RESPONSE_A, MODULE_RESOURCES_RESPONSE_A)
111 registerCmHandle(DMI_URL, 'ch-2', 'B', MODULE_REFERENCES_RESPONSE_B, MODULE_RESOURCES_RESPONSE_B)
112 assert ['M1', 'M2'] == objectUnderTest.getYangResourcesModuleReferences('ch-1').moduleName.sort()
113 assert ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences('ch-2').moduleName.sort()
115 when: 'a CM-handle is registered for creation with moduleSetTag "B"'
116 def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: 'ch-3', moduleSetTag: 'B')
117 networkCmProxyDataService.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: DMI_URL, createdCmHandles: [cmHandleToCreate]))
119 then: 'the CM-handle goes to READY state after module sync'
120 moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
121 new PollingConditions().within(3, () -> {
122 assert CmHandleState.READY == objectUnderTest.getCmHandleCompositeState('ch-3').cmHandleState
125 and: 'the CM-handle has expected modules from module set "B": M1 and M3'
126 ['M1', 'M3'] == objectUnderTest.getYangResourcesModuleReferences('ch-3').moduleName.sort()
128 cleanup: 'deregister CM handles'
129 deregisterCmHandles(DMI_URL, ['ch-1', 'ch-2', 'ch-3'])