NcmpCloudEventBuilder refactoring
[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 java.time.OffsetDateTime
24 import java.time.format.DateTimeFormatter
25 import org.onap.cps.api.CpsAnchorService
26 import org.onap.cps.api.CpsDataService
27 import org.onap.cps.api.CpsDataspaceService
28 import org.onap.cps.api.CpsModuleService
29 import org.onap.cps.api.CpsQueryService
30 import org.onap.cps.integration.DatabaseTestContainer
31 import org.onap.cps.integration.KafkaTestContainer
32 import org.onap.cps.ncmp.api.NetworkCmProxyCmHandleQueryService
33 import org.onap.cps.ncmp.api.NetworkCmProxyDataService
34 import org.onap.cps.ncmp.api.NetworkCmProxyQueryService
35 import org.onap.cps.ncmp.api.impl.inventory.CmHandleState
36 import org.onap.cps.ncmp.api.impl.inventory.sync.ModuleSyncWatchdog
37 import org.onap.cps.ncmp.api.models.DmiPluginRegistration
38 import org.onap.cps.ncmp.api.models.NcmpServiceCmHandle
39 import org.onap.cps.spi.exceptions.DataspaceNotFoundException
40 import org.onap.cps.spi.model.DataNode
41 import org.onap.cps.spi.repository.DataspaceRepository
42 import org.onap.cps.spi.utils.SessionManager
43 import org.onap.cps.utils.JsonObjectMapper
44 import org.springframework.beans.factory.annotation.Autowired
45 import org.springframework.boot.autoconfigure.EnableAutoConfiguration
46 import org.springframework.boot.autoconfigure.domain.EntityScan
47 import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
48 import org.springframework.boot.test.context.SpringBootTest
49 import org.springframework.context.annotation.ComponentScan
50 import org.springframework.data.jpa.repository.config.EnableJpaRepositories
51 import org.springframework.http.HttpStatus
52 import org.springframework.http.MediaType
53 import org.springframework.test.web.client.ExpectedCount
54 import org.springframework.test.web.client.MockRestServiceServer
55 import org.springframework.test.web.servlet.MockMvc
56 import org.springframework.web.client.RestTemplate
57 import org.testcontainers.spock.Testcontainers
58 import spock.lang.Shared
59 import spock.lang.Specification
60 import spock.util.concurrent.PollingConditions
61
62 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DATASPACE_NAME
63 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_ANCHOR
64 import static org.onap.cps.ncmp.api.impl.ncmppersistence.NcmpPersistence.NCMP_DMI_REGISTRY_PARENT
65 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo
66 import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus
67
68 @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = [CpsDataspaceService])
69 @Testcontainers
70 @EnableAutoConfiguration
71 @AutoConfigureMockMvc
72 @EnableJpaRepositories(basePackageClasses = [DataspaceRepository])
73 @ComponentScan(basePackages = ['org.onap.cps'])
74 @EntityScan('org.onap.cps.spi.entities')
75 abstract class CpsIntegrationSpecBase extends Specification {
76
77     @Shared
78     DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance()
79
80     @Shared
81     KafkaTestContainer kafkaTestContainer = KafkaTestContainer.getInstance()
82
83     @Autowired
84     MockMvc mvc
85
86     @Autowired
87     CpsDataspaceService cpsDataspaceService
88
89     @Autowired
90     CpsAnchorService cpsAnchorService
91
92     @Autowired
93     CpsDataService cpsDataService
94
95     @Autowired
96     CpsModuleService cpsModuleService
97
98     @Autowired
99     CpsQueryService cpsQueryService
100
101     @Autowired
102     SessionManager sessionManager
103
104     @Autowired
105     NetworkCmProxyCmHandleQueryService networkCmProxyCmHandleQueryService
106
107     @Autowired
108     NetworkCmProxyDataService networkCmProxyDataService
109
110     @Autowired
111     NetworkCmProxyQueryService networkCmProxyQueryService
112
113     @Autowired
114     RestTemplate restTemplate
115
116     @Autowired
117     ModuleSyncWatchdog moduleSyncWatchdog
118
119     @Autowired
120     JsonObjectMapper jsonObjectMapper
121
122     MockRestServiceServer mockDmiServer = null
123
124     static DMI_URL = 'http://mock-dmi-server'
125     static NO_MODULE_SET_TAG = ''
126     static GENERAL_TEST_DATASPACE = 'generalTestDataspace'
127     static BOOKSTORE_SCHEMA_SET = 'bookstoreSchemaSet'
128
129     def static initialized = false
130     def now = OffsetDateTime.now()
131
132     def setup() {
133         if (!initialized) {
134             cpsDataspaceService.createDataspace(GENERAL_TEST_DATASPACE)
135             createStandardBookStoreSchemaSet(GENERAL_TEST_DATASPACE)
136             initialized = true
137         }
138         mockDmiServer = MockRestServiceServer.bindTo(restTemplate).ignoreExpectOrder(true).build()
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 mockDmiResponsesForModuleSync(dmiPlugin, cmHandleId, dmiModuleReferencesResponse, dmiModuleResourcesResponse) {
221         mockDmiServer.expect(requestTo("${dmiPlugin}/dmi/v1/ch/${cmHandleId}/modules"))
222                 .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(dmiModuleReferencesResponse))
223         mockDmiServer.expect(requestTo("${dmiPlugin}/dmi/v1/ch/${cmHandleId}/moduleResources"))
224                 .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body(dmiModuleResourcesResponse))
225     }
226
227     def mockDmiIsNotAvailableForModuleSync(dmiPlugin, cmHandleId) {
228         mockDmiServer.expect(requestTo("${dmiPlugin}/dmi/v1/ch/${cmHandleId}/modules"))
229                 .andRespond(withStatus(HttpStatus.SERVICE_UNAVAILABLE))
230     }
231
232     def mockDmiWillRespondToHealthChecks(dmiPlugin) {
233         mockDmiServer.expect(ExpectedCount.between(0, Integer.MAX_VALUE), requestTo("${dmiPlugin}/actuator/health"))
234                 .andRespond(withStatus(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).body('{"status":"UP"}'))
235     }
236
237     def overrideCmHandleLastUpdateTime(cmHandleId, newUpdateTime) {
238         String ISO_TIMESTAMP_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
239         DateTimeFormatter ISO_TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern(ISO_TIMESTAMP_PATTERN);
240         def jsonForUpdate = '{ "state": { "last-update-time": "%s" } }'.formatted(ISO_TIMESTAMP_FORMATTER.format(newUpdateTime))
241         cpsDataService.updateNodeLeaves(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
242                 NCMP_DMI_REGISTRY_PARENT + "/cm-handles[@id='${cmHandleId}']", jsonForUpdate, now)
243     }
244 }