2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2023 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.ncmp.init
23 import ch.qos.logback.classic.Level
24 import ch.qos.logback.classic.Logger
25 import ch.qos.logback.core.read.ListAppender
26 import org.onap.cps.api.CpsAdminService
27 import org.onap.cps.api.CpsDataService
28 import org.onap.cps.api.CpsModuleService
29 import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException
30 import org.onap.cps.spi.exceptions.AlreadyDefinedException
31 import org.onap.cps.spi.exceptions.AlreadyDefinedExceptionBatch
32 import org.onap.cps.spi.exceptions.DataValidationException
33 import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
34 import org.onap.cps.spi.model.Dataspace
35 import org.springframework.boot.SpringApplication
36 import org.slf4j.LoggerFactory
37 import org.springframework.boot.context.event.ApplicationReadyEvent
38 import org.springframework.context.annotation.AnnotationConfigApplicationContext
39 import spock.lang.Specification
41 class SubscriptionModelLoaderSpec extends Specification {
43 def mockCpsAdminService = Mock(CpsAdminService)
44 def mockCpsModuleService = Mock(CpsModuleService)
45 def mockCpsDataService = Mock(CpsDataService)
46 def objectUnderTest = new SubscriptionModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsDataService)
48 def sampleYangContentMap = ['subscription.yang':'module subscription { *sample content* }']
50 def applicationContext = new AnnotationConfigApplicationContext()
52 def applicationReadyEvent = new ApplicationReadyEvent(new SpringApplication(), null, applicationContext, null)
54 def yangResourceToContentMap
55 def logger = (Logger) LoggerFactory.getLogger(objectUnderTest.getClass())
56 def loggingListAppender
59 yangResourceToContentMap = objectUnderTest.createYangResourceToContentMap()
60 logger.setLevel(Level.DEBUG)
61 loggingListAppender = new ListAppender()
62 logger.addAppender(loggingListAppender)
63 loggingListAppender.start()
64 applicationContext.refresh()
68 ((Logger) LoggerFactory.getLogger(SubscriptionModelLoader.class)).detachAndStopAllAppenders()
69 applicationContext.close()
72 def 'Onboard subscription model successfully via application ready event'() {
73 given: 'dataspace is ready for use'
74 mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('NCMP-Admin')
75 and:'model loader is enabled'
76 objectUnderTest.subscriptionModelLoaderEnabled = true
77 and: 'maximum attempt count is set'
78 objectUnderTest.maximumAttemptCount = 20
79 and: 'retry time is set'
80 objectUnderTest.retryTimeMs = 100
81 when: 'the application is ready'
82 objectUnderTest.onApplicationEvent(applicationReadyEvent)
83 then: 'the module service to create schema set is called once'
84 1 * mockCpsModuleService.createSchemaSet('NCMP-Admin', 'subscriptions',sampleYangContentMap)
85 and: 'the admin service to create an anchor set is called once'
86 1 * mockCpsAdminService.createAnchor('NCMP-Admin', 'subscriptions', 'AVC-Subscriptions')
87 and: 'the data service to create a top level datanode is called once'
88 1 * mockCpsDataService.saveData('NCMP-Admin', 'AVC-Subscriptions', '{"subscription-registry":{}}', _)
91 def 'No subscription model onboarding when subscription model loader is disabled' () {
92 when: 'model loader is disabled'
93 objectUnderTest.subscriptionModelLoaderEnabled = false
94 and: 'application is ready'
95 objectUnderTest.onApplicationEvent(applicationReadyEvent)
96 and: 'dataspace is ready for use'
97 mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('NCMP-Admin')
98 then: 'the module service to create schema set was not called'
99 0 * mockCpsModuleService.createSchemaSet(*_)
100 and: 'the admin service to create an anchor set was not called'
101 0 * mockCpsAdminService.createAnchor(*_)
102 and: 'the data service to create a top level datanode was not called'
103 0 * mockCpsDataService.saveData(*_)
106 def 'Onboard subscription model fails as NCMP dataspace does not exist' () {
107 given: 'model loader is enabled'
108 objectUnderTest.subscriptionModelLoaderEnabled = true
109 and: 'maximum attempt count is set'
110 objectUnderTest.maximumAttemptCount = 20
111 and: 'retry time is set'
112 objectUnderTest.retryTimeMs = 100
113 when: 'the application is ready'
114 objectUnderTest.onApplicationEvent(applicationReadyEvent)
115 then: 'the module service to create schema set was not called'
116 0 * mockCpsModuleService.createSchemaSet(*_)
117 and: 'the admin service to create an anchor set was not called'
118 0 * mockCpsAdminService.createAnchor(*_)
119 and: 'the data service to create a top level datanode was not called'
120 0 * mockCpsDataService.saveData(*_)
121 and: 'the log message contains the correct exception message'
122 def logs = loggingListAppender.list.toString()
123 assert logs.contains("Retrieval of NCMP dataspace fails")
127 def 'Exception occurred while schema set creation' () {
128 given: 'creating a schema set throws an exception'
129 mockCpsModuleService.createSchemaSet(*_) >> { throw new DataValidationException(*_) }
130 and: 'model loader is enabled'
131 objectUnderTest.subscriptionModelLoaderEnabled = true
132 and: 'dataspace is ready for use'
133 mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('NCMP-Admin')
134 when: 'application is ready'
135 objectUnderTest.onApplicationEvent(applicationReadyEvent)
136 then: 'the admin service to create an anchor set was not called'
137 0 * mockCpsAdminService.createAnchor(*_)
138 and: 'the data service to create a top level datanode was not called'
139 0 * mockCpsDataService.saveData(*_)
142 def 'Create schema set from model file'() {
143 when: 'the method to create schema set is called with the following parameters'
144 objectUnderTest.createSchemaSet("myDataspace", "mySchemaSet", yangResourceToContentMap)
145 then: 'yang resource to content map is as expected'
146 assert sampleYangContentMap == yangResourceToContentMap
147 and: 'the module service to create schema set is called once with the correct map'
148 1 * mockCpsModuleService.createSchemaSet(_, _, yangResourceToContentMap)
151 def 'Create schema set fails due to AlreadyDefined exception'() {
152 given: 'creating a schema set throws an exception as it already exists'
153 mockCpsModuleService.createSchemaSet('NCMP-Admin', 'subscriptions', yangResourceToContentMap) >>
154 { throw AlreadyDefinedException.forSchemaSet('subscriptions', "sampleContextName", null) }
155 when: 'the method to onboard model is called'
156 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
157 then: 'the admin service to create an anchor set is then called once'
158 1 * mockCpsAdminService.createAnchor('NCMP-Admin', 'subscriptions', 'AVC-Subscriptions')
161 def 'Create schema set fails due to any other exception'() {
162 given: 'creating a schema set throws an exception'
163 mockCpsModuleService.createSchemaSet(*_) >> { throw new NcmpStartUpException("Creating schema set failed", "") }
164 when: 'the method to onboard model is called'
165 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
166 then: 'the log message contains the correct exception message'
167 def debugMessage = loggingListAppender.list[0].toString()
168 assert debugMessage.contains("Creating schema set failed")
169 and: 'exception is thrown'
170 thrown(NcmpStartUpException)
173 def 'Create anchor fails due to AlreadyDefined exception'() {
174 given: 'creating anchor throws an exception as it already exists'
175 mockCpsAdminService.createAnchor(*_) >>
176 { throw AlreadyDefinedException.forSchemaSet('subscriptions', "sampleContextName", null) }
177 when: 'the method to onboard model is called'
178 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
179 then: 'no exception thrown'
181 and: 'the log message contains the correct exception message'
182 def infoMessage = loggingListAppender.list[0].toString()
183 assert infoMessage.contains("already exists")
186 def 'Create anchor fails due to any other exception'() {
187 given: 'creating an anchor failed'
188 mockCpsAdminService.createAnchor(*_) >>
189 { throw new SchemaSetNotFoundException('NCMP-Admin', 'subscriptions') }
190 when: 'the method to onboard model is called'
191 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
192 then: 'the log message contains the correct exception message'
193 def debugMessage = loggingListAppender.list[0].toString()
194 assert debugMessage.contains("Schema Set not found")
195 and: 'exception is thrown'
196 thrown(NcmpStartUpException)
199 def 'Create top level node fails due to an AlreadyDefined exception'() {
200 given: 'the saving of the node data will throw an Already Defined exception'
201 mockCpsDataService.saveData(*_) >>
202 { throw new AlreadyDefinedExceptionBatch(['/xpath']) }
203 when: 'the method to onboard model is called'
204 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
205 then: 'no exception thrown'
207 and: 'the log message contains the correct exception message'
208 def infoMessage = loggingListAppender.list[0].toString()
209 assert infoMessage.contains("already exists")
212 def 'Create top level node fails due to any other exception'() {
213 given: 'the saving of the node data will throw an exception'
214 mockCpsDataService.saveData(*_) >>
215 { throw new DataValidationException("Invalid JSON", "JSON Data is invalid") }
216 when: 'the method to onboard model is called'
217 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
218 then: 'the log message contains the correct exception message'
219 def debugMessage = loggingListAppender.list[0].toString()
220 assert debugMessage.contains("Creating data node for subscription model failed: Invalid JSON")
221 and: 'exception is thrown'
222 thrown(NcmpStartUpException)
225 def 'Get file content as string'() {
226 when: 'the method to get yang content is called'
227 objectUnderTest.getFileContentAsString('NonExistingFile')
228 then: 'exception is thrown'
229 thrown(NcmpStartUpException)