2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2022 Bell Canada
4 * Modifications Copyright (C) 2022 Nordix Foundation
5 * ================================================================================
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * SPDX-License-Identifier: Apache-2.0
19 * ============LICENSE_END=========================================================
22 package org.onap.cps.api.impl
24 import org.onap.cps.TestUtils
25 import org.onap.cps.spi.CpsModulePersistenceService
26 import org.onap.cps.spi.exceptions.DataValidationException
27 import org.onap.cps.yang.YangTextSchemaSourceSet
28 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
29 import org.spockframework.spring.SpringBean
30 import org.springframework.beans.factory.annotation.Autowired
31 import org.springframework.boot.test.context.SpringBootTest
32 import org.springframework.cache.Cache
33 import org.springframework.cache.CacheManager
34 import org.springframework.cache.annotation.EnableCaching
35 import org.springframework.cache.caffeine.CaffeineCacheManager
36 import org.springframework.test.context.ContextConfiguration
37 import spock.lang.Specification
41 @ContextConfiguration(classes = [YangTextSchemaSourceSetCache, CaffeineCacheManager])
42 class YangTextSchemaSourceSetCacheSpec extends Specification {
45 CpsModulePersistenceService mockModuleStoreService = Mock()
48 YangTextSchemaSourceSetCache objectUnderTest
51 CacheManager cacheManager
53 Cache yangResourceCacheImpl;
56 yangResourceCacheImpl = cacheManager.getCache('yangSchema')
57 yangResourceCacheImpl.clear()
61 def 'Cache Miss: Fetch data from Module persistence'() {
62 given: 'cache is empty'
63 yangResourceCacheImpl.clear()
64 and: 'a schema set exists'
65 def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
66 def expectedYangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
67 when: 'schema-set information is asked'
68 def result = objectUnderTest.get('my-dataspace', 'my-schemaset')
69 then: 'information fetched from cps module persistence'
70 1 * mockModuleStoreService.getYangSchemaResources('my-dataspace', 'my-schemaset')
71 >> yangResourcesNameToContentMap
72 and: 'stored in the cache'
73 def cachedValue = getCachedValue('my-dataspace', 'my-schemaset')
74 assert cachedValue.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
75 and: 'the response is as expected'
76 assert result.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
79 def 'Cache Hit: Respond from cache'() {
80 given: 'a schema set exists'
81 def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
82 def expectedYangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
83 and: 'stored in cache'
84 yangResourceCacheImpl.put(getCacheKey('my-dataspace', 'my-schemaset'), expectedYangTextSchemaSourceSet)
85 when: 'schema-set information is asked'
86 def result = objectUnderTest.get('my-dataspace', 'my-schemaset')
87 then: 'expected value is returned'
88 result.getModuleReferences() == expectedYangTextSchemaSourceSet.getModuleReferences()
89 and: 'module persistence is not invoked'
90 0 * mockModuleStoreService.getYangSchemaResources(_, _)
93 def 'Cache Hit: with invalid #scenario'() {
94 when: 'schema-set information is asked'
95 objectUnderTest.get(dataspaceName, schemaSetName)
96 then: 'an data validation exception is thrown'
97 thrown(DataValidationException)
98 and: 'module persistence is not invoked'
99 0 * mockModuleStoreService.getYangSchemaResources(_, _)
100 where: 'the following parameters are used'
101 scenario | dataspaceName | schemaSetName
102 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
103 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
104 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
107 def 'Cache Update: when no data exist in the cache'() {
108 given: 'a schema set exists'
109 def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
110 def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
111 when: 'cache is updated'
112 objectUnderTest.updateCache('my-dataspace', 'my-schemaset', yangTextSchemaSourceSet)
113 then: 'cached value is same as expected'
114 def cachedValue = getCachedValue('my-dataspace', 'my-schemaset')
115 cachedValue.getModuleReferences() == yangTextSchemaSourceSet.getModuleReferences()
118 def 'Cache Update: with invalid #scenario'() {
119 given: 'a schema set exists'
120 def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
121 def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
122 when: 'schema-set information is asked'
123 objectUnderTest.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet)
124 then: 'an data validation exception is thrown'
125 thrown(DataValidationException)
126 and: 'module persistence is not invoked'
127 0 * mockModuleStoreService.getYangSchemaResources(_, _)
128 where: 'the following parameters are used'
129 scenario | dataspaceName | schemaSetName
130 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
131 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
132 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
135 def 'Cache Evict:with invalid #scenario'() {
136 given: 'a schema set exists in cache'
137 def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
138 def yangTextSchemaSourceSet = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap)
139 yangResourceCacheImpl.put(getCacheKey('my-dataspace', 'my-schemaset'), yangTextSchemaSourceSet)
140 def cachedValue = getCachedValue('my-dataspace', 'my-schemaset')
141 assert cachedValue.getModuleReferences() == yangTextSchemaSourceSet.getModuleReferences()
142 when: 'cache is evicted for schemaset'
143 objectUnderTest.removeFromCache('my-dataspace', 'my-schemaset')
144 then: 'cached does not have value'
145 assert getCachedValue('my-dataspace', 'my-schemaset') == null
148 def 'Cache Evict: remove when exist'() {
149 when: 'cache is evicted for schemaset'
150 objectUnderTest.removeFromCache(dataspaceName, schemaSetName)
151 then: 'an data validation exception is thrown'
152 thrown(DataValidationException)
153 where: 'the following parameters are used'
154 scenario | dataspaceName | schemaSetName
155 'dataspace name' | 'dataspace names with spaces' | 'schemaSetName'
156 'schema set name' | 'dataspaceName' | 'schema set name with spaces'
157 'dataspace and schema set name' | 'dataspace name with spaces' | 'schema set name with spaces'
160 def 'Cache Evict: remove when does not exist'() {
161 given: 'cache is empty'
162 yangResourceCacheImpl.clear()
163 when: 'cache is evicted for schemaset'
164 objectUnderTest.removeFromCache('my-dataspace', 'my-schemaset')
165 then: 'cached does not have value'
166 assert getCachedValue('my-dataspace', 'my-schemaset') == null
169 def getCachedValue(dataSpace, schemaSet) {
170 yangResourceCacheImpl.get(getCacheKey(dataSpace, schemaSet), YangTextSchemaSourceSet)
173 def getCacheKey(dataSpace, schemaSet) {
174 return new String("${dataSpace}-${schemaSet}")