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