Make NCMP integration tests use MockWebServer
[cps.git] / integration-test / src / test / groovy / org / onap / cps / integration / base / CpsIntegrationSpecBase.groovy
1 /*
2  *  ============LICENSE_START=======================================================
3  *  Copyright (C) 2023-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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  *  SPDX-License-Identifier: Apache-2.0
18  *  ============LICENSE_END=========================================================
19  */
20
21 package org.onap.cps.integration.base
22
23 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
24 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
25 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
26
27 import java.time.OffsetDateTime
28 import java.time.format.DateTimeFormatter
29 import okhttp3.mockwebserver.MockWebServer
30 import org.onap.cps.api.CpsAnchorService
31 import org.onap.cps.api.CpsDataService
32 import org.onap.cps.api.CpsDataspaceService
33 import org.onap.cps.api.CpsModuleService
34 import org.onap.cps.api.CpsQueryService
35 import org.onap.cps.integration.DatabaseTestContainer
36 import org.onap.cps.integration.KafkaTestContainer
37 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
38 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
39 import org.onap.cps.ncmp.api.NetworkCmProxyQueryService
40 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
41 import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncWatchdog
42 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
43 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
44 import org.onap.cps.spi.exceptions.DataspaceNotFoundException
45 import org.onap.cps.spi.model.DataNode
46 import org.onap.cps.spi.repository.DataspaceRepository
47 import org.onap.cps.spi.utils.SessionManager
48 import org.onap.cps.utils.JsonObjectMapper
49 import org.springframework.beans.factory.annotation.Autowired
50 import org.springframework.boot.autoconfigure.EnableAutoConfiguration
51 import org.springframework.boot.autoconfigure.domain.EntityScan
52 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
53 import org.springframework.boot.test.context.SpringBootTest
54 import org.springframework.context.annotation.ComponentScan
55 import org.springframework.data.jpa.repository.config.EnableJpaRepositories
56 import org.springframework.test.web.servlet.MockMvc
57 import org.testcontainers.spock.Testcontainers
58 import spock.lang.Shared
59 import spock.lang.Specification
60 import spock.util.concurrent.PollingConditions
61
62 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = [CpsDataspaceService])
63 @Testcontainers
64 @EnableAutoConfiguration
65 @AutoConfigureMockMvc
66 @EnableJpaRepositories(basePackageClasses = [DataspaceRepository])
67 @ComponentScan(basePackages = ['org.onap.cps'])
68 @EntityScan('org.onap.cps.spi.entities')
69 abstract class CpsIntegrationSpecBase extends Specification {
70
71     @Shared
72     DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance()
73
74     @Shared
75     KafkaTestContainer kafkaTestContainer = KafkaTestContainer.getInstance()
76
77     @Autowired
78     MockMvc mvc
79
80     @Autowired
81     CpsDataspaceService cpsDataspaceService
82
83     @Autowired
84     CpsAnchorService cpsAnchorService
85
86     @Autowired
87     CpsDataService cpsDataService
88
89     @Autowired
90     CpsModuleService cpsModuleService
91
92     @Autowired
93     CpsQueryService cpsQueryService
94
95     @Autowired
96     SessionManager sessionManager
97
98     @Autowired
99     NetworkCmProxyCmHandleQueryService networkCmProxyCmHandleQueryService
100
101     @Autowired
102     NetworkCmProxyDataService networkCmProxyDataService
103
104     @Autowired
105     NetworkCmProxyQueryService networkCmProxyQueryService
106
107     @Autowired
108     ModuleSyncWatchdog moduleSyncWatchdog
109
110     @Autowired
111     JsonObjectMapper jsonObjectMapper
112
113     MockWebServer mockDmiServer = null
114     DmiDispatcher dmiDispatcher = new DmiDispatcher()
115
116     def DMI_URL = null
117
118     static NO_MODULE_SET_TAG = ''
119     static GENERAL_TEST_DATASPACE = 'generalTestDataspace'
120     static BOOKSTORE_SCHEMA_SET = 'bookstoreSchemaSet'
121
122     def static initialized = false
123     def now = OffsetDateTime.now()
124
125     def setup() {
126         if (!initialized) {
127             cpsDataspaceService.createDataspace(GENERAL_TEST_DATASPACE)
128             createStandardBookStoreSchemaSet(GENERAL_TEST_DATASPACE)
129             initialized = true
130         }
131         mockDmiServer = new MockWebServer()
132         mockDmiServer.setDispatcher(dmiDispatcher)
133         mockDmiServer.start()
134         DMI_URL = String.format("http://%s:%s", mockDmiServer.getHostName(), mockDmiServer.getPort())
135     }
136
137     def cleanup() {
138         mockDmiServer.shutdown()
139     }
140
141     def static readResourceDataFile(filename) {
142         return new File('src/test/resources/data/' + filename).text
143     }
144
145     // *** CPS Integration Test Utilities ***
146
147     def static countDataNodesInTree(DataNode dataNode) {
148         return 1 + countDataNodesInTree(dataNode.getChildDataNodes())
149     }
150
151     def static countDataNodesInTree(Collection<DataNode> dataNodes) {
152         int nodeCount = 0
153         for (DataNode parent : dataNodes) {
154             nodeCount += countDataNodesInTree(parent)
155         }
156         return nodeCount
157     }
158
159     def getBookstoreYangResourcesNameToContentMap() {
160         def bookstoreModelFileContent = readResourceDataFile('bookstore/bookstore.yang')
161         def bookstoreTypesFileContent = readResourceDataFile('bookstore/bookstore-types.yang')
162         return [bookstore: bookstoreModelFileContent, bookstoreTypes: bookstoreTypesFileContent]
163     }
164
165     def createStandardBookStoreSchemaSet(targetDataspace) {
166         cpsModuleService.createSchemaSet(targetDataspace, BOOKSTORE_SCHEMA_SET, getBookstoreYangResourcesNameToContentMap())
167     }
168
169     def createStandardBookStoreSchemaSet(targetDataspace, targetSchemaSet) {
170         cpsModuleService.createSchemaSet(targetDataspace, targetSchemaSet, getBookstoreYangResourcesNameToContentMap())
171     }
172
173     def dataspaceExists(dataspaceName) {
174         try {
175             cpsDataspaceService.getDataspace(dataspaceName)
176         } catch (DataspaceNotFoundException ignored) {
177             return false
178         }
179         return true
180     }
181
182     def addAnchorsWithData(numberOfAnchors, dataspaceName, schemaSetName, anchorNamePrefix, data) {
183         (1..numberOfAnchors).each {
184             cpsAnchorService.createAnchor(dataspaceName, schemaSetName, anchorNamePrefix + it)
185             cpsDataService.saveData(dataspaceName, anchorNamePrefix + it, data.replace("Easons", "Easons-"+it.toString()), OffsetDateTime.now())
186         }
187     }
188
189     def createJsonArray(name, numberOfElements, keyName, keyValuePrefix, dataPerKey) {
190         def innerJson = (1..numberOfElements).collect {
191             '{"' + keyName + '":"' + keyValuePrefix + '-' + it + '"' + (dataPerKey.empty? '': ',' + dataPerKey) + '}'
192         }.join(',')
193         return '{"' + name + '":[' + innerJson + ']}'
194     }
195
196     def createLeafList(name, numberOfElements, valuePrefix) {
197         def innerJson = (1..numberOfElements).collect {'"' + valuePrefix + '-' + it + '"'}.join(',')
198         return '"' + name + '":[' + innerJson + ']'
199     }
200
201     // *** NCMP Integration Test Utilities ***
202
203     def registerCmHandle(dmiPlugin, cmHandleId, moduleSetTag) {
204         def cmHandleToCreate = new NcmpServiceCmHandle(cmHandleId: cmHandleId, moduleSetTag: moduleSetTag)
205         networkCmProxyDataService.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: dmiPlugin, createdCmHandles: [cmHandleToCreate]))
206         moduleSyncWatchdog.moduleSyncAdvisedCmHandles()
207         new PollingConditions().within(3, () -> {
208             CmHandleState.READY == networkCmProxyDataService.getCmHandleCompositeState(cmHandleId).cmHandleState
209         })
210     }
211
212     def deregisterCmHandle(dmiPlugin, cmHandleId) {
213         deregisterCmHandles(dmiPlugin, [cmHandleId])
214     }
215
216     def deregisterCmHandles(dmiPlugin, cmHandleIds) {
217         networkCmProxyDataService.updateDmiRegistrationAndSyncModule(new DmiPluginRegistration(dmiPlugin: dmiPlugin, removedCmHandles: cmHandleIds))
218     }
219
220     def overrideCmHandleLastUpdateTime(cmHandleId, newUpdateTime) {
221         String ISO_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
222         DateTimeFormatter ISO_TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(ISO_TIMESTAMP_PATTERN);
223         def jsonForUpdate = '{ "state": { "last-update-time": "%s" } }'.formatted(ISO_TIMESTAMP_FORMATTER.format(newUpdateTime))
224         cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
225                 NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='${cmHandleId}']", jsonForUpdate, now)
226     }
227 }