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.junit.jupiter.api.AfterEach
27 import org.junit.jupiter.api.BeforeEach
28 import org.onap.cps.api.CpsAdminService
29 import org.onap.cps.api.CpsDataService
30 import org.onap.cps.api.CpsModuleService
31 import org.onap.cps.ncmp.api.impl.exception.NcmpStartUpException
32 import org.onap.cps.spi.exceptions.AlreadyDefinedException
33 import org.onap.cps.spi.exceptions.DataValidationException
34 import org.onap.cps.spi.exceptions.SchemaSetNotFoundException
35 import org.onap.cps.spi.model.Dataspace
36 import org.springframework.boot.SpringApplication
37 import org.slf4j.LoggerFactory
38 import org.springframework.boot.context.event.ApplicationReadyEvent
39 import org.springframework.context.annotation.AnnotationConfigApplicationContext
40 import spock.lang.Specification
42 class SubscriptionModelLoaderSpec extends Specification {
44 def mockCpsAdminService = Mock(CpsAdminService)
45 def mockCpsModuleService = Mock(CpsModuleService)
46 def mockCpsDataService = Mock(CpsDataService)
47 def objectUnderTest = new SubscriptionModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsDataService)
49 def sampleYangContentMap = ['subscription.yang':'module subscription { *sample content* }']
51 def applicationContext = new AnnotationConfigApplicationContext()
53 def applicationReadyEvent = new ApplicationReadyEvent(new SpringApplication(), null, applicationContext, null)
55 def yangResourceToContentMap
61 yangResourceToContentMap = objectUnderTest.createYangResourceToContentMap()
62 logger = (Logger) LoggerFactory.getLogger(objectUnderTest.getClass())
63 appender = new ListAppender()
64 logger.setLevel(Level.DEBUG)
66 logger.addAppender(appender)
67 applicationContext.refresh()
72 ((Logger) LoggerFactory.getLogger(SubscriptionModelLoader.class)).detachAndStopAllAppenders()
73 applicationContext.close()
76 def 'Onboard subscription model successfully via application ready event'() {
77 given: 'dataspace is ready for use'
78 mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('NCMP-Admin')
79 and:'model loader is enabled'
80 objectUnderTest.subscriptionModelLoaderEnabled = true
81 and: 'maximum attempt count is set'
82 objectUnderTest.maximumAttemptCount = 20
83 and: 'retry time is set'
84 objectUnderTest.retryTimeMs = 100
85 when: 'the application is ready'
86 objectUnderTest.onApplicationEvent(applicationReadyEvent)
87 then: 'the module service to create schema set is called once'
88 1 * mockCpsModuleService.createSchemaSet('NCMP-Admin', 'subscriptions',sampleYangContentMap)
89 and: 'the admin service to create an anchor set is called once'
90 1 * mockCpsAdminService.createAnchor('NCMP-Admin', 'subscriptions', 'AVC-Subscriptions')
91 and: 'the data service to create a top level datanode is called once'
92 1 * mockCpsDataService.saveData('NCMP-Admin', 'AVC-Subscriptions', '{"subscription-registry":{}}', _)
95 def 'No subscription model onboarding when subscription model loader is disabled' () {
96 when: 'model loader is disabled'
97 objectUnderTest.subscriptionModelLoaderEnabled = false
98 and: 'application is ready'
99 objectUnderTest.onApplicationEvent(applicationReadyEvent)
100 and: 'dataspace is ready for use'
101 mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('NCMP-Admin')
102 then: 'the module service to create schema set was not called'
103 0 * mockCpsModuleService.createSchemaSet(*_)
104 and: 'the admin service to create an anchor set was not called'
105 0 * mockCpsAdminService.createAnchor(*_)
106 and: 'the data service to create a top level datanode was not called'
107 0 * mockCpsDataService.saveData(*_)
110 def 'Onboard subscription model fails as NCMP dataspace does not exist' () {
111 given: 'model loader is enabled'
112 objectUnderTest.subscriptionModelLoaderEnabled = true
113 and: 'maximum attempt count is set'
114 objectUnderTest.maximumAttemptCount = 20
115 and: 'retry time is set'
116 objectUnderTest.retryTimeMs = 100
117 when: 'the application is ready'
118 objectUnderTest.onApplicationEvent(applicationReadyEvent)
119 then: 'the module service to create schema set was not called'
120 0 * mockCpsModuleService.createSchemaSet(*_)
121 and: 'the admin service to create an anchor set was not called'
122 0 * mockCpsAdminService.createAnchor(*_)
123 and: 'the data service to create a top level datanode was not called'
124 0 * mockCpsDataService.saveData(*_)
125 and: 'the log message contains the correct exception message'
126 def logs = appender.list.toString()
127 assert logs.contains("Retrieval of NCMP dataspace fails")
131 def 'Exception occurred while schema set creation' () {
132 given: 'creating a schema set throws an exception'
133 mockCpsModuleService.createSchemaSet(*_) >> { throw new DataValidationException(*_) }
134 and: 'model loader is enabled'
135 objectUnderTest.subscriptionModelLoaderEnabled = true
136 and: 'dataspace is ready for use'
137 mockCpsAdminService.getDataspace('NCMP-Admin') >> new Dataspace('NCMP-Admin')
138 when: 'application is ready'
139 objectUnderTest.onApplicationEvent(applicationReadyEvent)
140 then: 'the admin service to create an anchor set was not called'
141 0 * mockCpsAdminService.createAnchor(*_)
142 and: 'the data service to create a top level datanode was not called'
143 0 * mockCpsDataService.saveData(*_)
146 def 'Create schema set from model file'() {
147 when: 'the method to create schema set is called with the following parameters'
148 objectUnderTest.createSchemaSet("myDataspace", "mySchemaSet", yangResourceToContentMap)
149 then: 'yang resource to content map is as expected'
150 assert sampleYangContentMap == yangResourceToContentMap
151 and: 'the module service to create schema set is called once with the correct map'
152 1 * mockCpsModuleService.createSchemaSet(_, _, yangResourceToContentMap)
155 def 'Create schema set fails due to AlreadyDefined exception'() {
156 given: 'creating a schema set throws an exception as it already exists'
157 mockCpsModuleService.createSchemaSet('NCMP-Admin', 'subscriptions', yangResourceToContentMap) >>
158 { throw AlreadyDefinedException.forSchemaSet('subscriptions', "sampleContextName", null) }
159 when: 'the method to onboard model is called'
160 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
161 then: 'the admin service to create an anchor set is then called once'
162 1 * mockCpsAdminService.createAnchor('NCMP-Admin', 'subscriptions', 'AVC-Subscriptions')
165 def 'Create schema set fails due to any other exception'() {
166 given: 'creating a schema set throws an exception'
167 mockCpsModuleService.createSchemaSet(*_) >> { throw new NcmpStartUpException("Creating schema set failed", "") }
168 when: 'the method to onboard model is called'
169 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
170 then: 'the log message contains the correct exception message'
171 def debugMessage = appender.list[0].toString()
172 assert debugMessage.contains("Creating schema set failed")
173 and: 'exception is thrown'
174 thrown(NcmpStartUpException)
177 def 'Create anchor fails due to AlreadyDefined exception'() {
178 given: 'creating anchor throws an exception as it already exists'
179 mockCpsAdminService.createAnchor(*_) >>
180 { throw AlreadyDefinedException.forSchemaSet('subscriptions', "sampleContextName", null) }
181 when: 'the method to onboard model is called'
182 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
183 then: 'no exception thrown'
185 and: 'the log message contains the correct exception message'
186 def infoMessage = appender.list[0].toString()
187 assert infoMessage.contains("already exists")
190 def 'Create anchor fails due to any other exception'() {
191 given: 'creating an anchor failed'
192 mockCpsAdminService.createAnchor(*_) >>
193 { throw new SchemaSetNotFoundException('NCMP-Admin', 'subscriptions') }
194 when: 'the method to onboard model is called'
195 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
196 then: 'the log message contains the correct exception message'
197 def debugMessage = appender.list[0].toString()
198 assert debugMessage.contains("Schema Set not found")
199 and: 'exception is thrown'
200 thrown(NcmpStartUpException)
203 def 'Create top level node fails due to an AlreadyDefined exception'() {
204 given: 'the saving of the node data will throw an Already Defined exception'
205 mockCpsDataService.saveData(*_) >>
206 { throw AlreadyDefinedException.forDataNode('/xpath', "sampleContextName", null) }
207 when: 'the method to onboard model is called'
208 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
209 then: 'no exception thrown'
211 and: 'the log message contains the correct exception message'
212 def infoMessage = appender.list[0].toString()
213 assert infoMessage.contains("already exists")
216 def 'Create top level node fails due to any other exception'() {
217 given: 'the saving of the node data will throw an exception'
218 mockCpsDataService.saveData(*_) >>
219 { throw new DataValidationException("Invalid JSON", "JSON Data is invalid") }
220 when: 'the method to onboard model is called'
221 objectUnderTest.onboardSubscriptionModel(yangResourceToContentMap)
222 then: 'the log message contains the correct exception message'
223 def debugMessage = appender.list[0].toString()
224 assert debugMessage.contains("Creating data node for subscription model failed: Invalid JSON")
225 and: 'exception is thrown'
226 thrown(NcmpStartUpException)
229 def 'Get file content as string'() {
230 when: 'the method to get yang content is called'
231 objectUnderTest.getFileContentAsString('NonExistingFile')
232 then: 'exception is thrown'
233 thrown(NcmpStartUpException)