2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2021 Nordix Foundation
4 * Modifications Copyright (C) 2021 Pantheon.tech
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
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.api.impl
23 import org.onap.cps.TestUtils
24 import org.onap.cps.api.CpsAdminService
25 import org.onap.cps.api.CpsModuleService
26 import org.onap.cps.spi.CpsDataPersistenceService
27 import org.onap.cps.spi.FetchDescendantsOption
28 import org.onap.cps.spi.model.Anchor
29 import org.onap.cps.spi.model.DataNodeBuilder
30 import org.onap.cps.yang.YangTextSchemaSourceSet
31 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
32 import spock.lang.Specification
33 import spock.lang.Unroll
35 class CpsDataServiceImplSpec extends Specification {
36 def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
37 def mockCpsAdminService = Mock(CpsAdminService)
38 def mockCpsModuleService = Mock(CpsModuleService)
39 def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
41 def objectUnderTest = new CpsDataServiceImpl()
44 objectUnderTest.cpsDataPersistenceService = mockCpsDataPersistenceService
45 objectUnderTest.cpsAdminService = mockCpsAdminService
46 objectUnderTest.cpsModuleService = mockCpsModuleService
47 objectUnderTest.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache
50 def dataspaceName = 'some dataspace'
51 def anchorName = 'some anchor'
52 def schemaSetName = 'some schema set'
54 def 'Saving json data.'() {
55 given: 'that the admin service will return an anchor'
56 def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
57 mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
58 and: 'the schema source set cache returns a schema source set'
59 def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
60 mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
61 and: 'the schema source sets returns the test-tree schema context'
62 def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
63 def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
64 mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
65 when: 'save data method is invoked with test-tree json data'
66 def jsonData = TestUtils.getResourceFileContent('test-tree.json')
67 objectUnderTest.saveData(dataspaceName, anchorName, jsonData)
68 then: 'the persistence service method is invoked with correct parameters'
69 1 * mockCpsDataPersistenceService.storeDataNode(dataspaceName, anchorName,
70 { dataNode -> dataNode.xpath == '/test-tree' })
73 def 'Saving child data fragment under existing node.'() {
74 given: 'that the admin service will return an anchor'
75 def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
76 mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
77 and: 'the schema source set cache returns a schema source set'
78 def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
79 mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
80 and: 'the schema source sets returns the test-tree schema context'
81 def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
82 def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
83 mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
84 when: 'save data method is invoked with test-tree json data'
85 def jsonData = '{"branch": [{"name": "New"}]}'
86 objectUnderTest.saveData(dataspaceName, anchorName, '/test-tree',jsonData)
87 then: 'the persistence service method is invoked with correct parameters'
88 1 * mockCpsDataPersistenceService.addChildDataNode(dataspaceName, anchorName,'/test-tree',
89 { dataNode -> dataNode.xpath == '/test-tree/branch[@name=\'New\']' })
93 def 'Get data node with option #fetchDescendantsOption.'() {
95 def dataNode = new DataNodeBuilder().withXpath(xpath).build()
96 given: 'persistence service returns data for get data request'
97 mockCpsDataPersistenceService.getDataNode(dataspaceName, anchorName, xpath, fetchDescendantsOption) >> dataNode
98 expect: 'service returns same data if uses same parameters'
99 objectUnderTest.getDataNode(dataspaceName, anchorName, xpath, fetchDescendantsOption) == dataNode
100 where: 'all fetch options are supported'
101 fetchDescendantsOption << FetchDescendantsOption.values()
105 def 'Update data node leaves: #scenario.'() {
106 given: 'that the admin service will return an anchor'
107 def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
108 mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
109 and: 'the schema source set cache returns a schema source set'
110 def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
111 mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
112 and: 'the schema source sets returns the test-tree schema context'
113 def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
114 def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
115 mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
116 when: 'update data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
117 objectUnderTest.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath, jsonData)
118 then: 'the persistence service method is invoked with correct parameters'
119 1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, nodeXpath, leaves)
120 where: 'following parameters were used'
121 scenario | parentNodeXpath | jsonData | nodeXpath | leaves
122 'top level node' | '/' | '{ "test-tree": {"branch": []}}' | '/test-tree' | Collections.emptyMap()
123 'level 2 node' | '/test-tree' | '{"branch": [{"name":"Name"}]}' | '/test-tree/branch[@name=\'Name\']' | ['name': 'Name']
127 def 'Replace data node: #scenario.'() {
128 given: 'that the admin service will return an anchor'
129 def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
130 mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
131 and: 'the schema source set cache returns a schema source set'
132 def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
133 mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
134 and: 'the schema source sets returns the test-tree schema context'
135 def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
136 def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
137 mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
138 when: 'replace data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
139 objectUnderTest.replaceNodeTree(dataspaceName, anchorName, parentNodeXpath, jsonData)
140 then: 'the persistence service method is invoked with correct parameters'
141 1 * mockCpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName,
142 { dataNode -> dataNode.xpath == nodeXpath })
143 where: 'following parameters were used'
144 scenario | parentNodeXpath | jsonData | nodeXpath
145 'top level node' | '/' | '{ "test-tree": {"branch": []}}' | '/test-tree'
146 'level 2 node' | '/test-tree' | '{"branch": [{"name":"Name"}]}' | '/test-tree/branch[@name=\'Name\']'