Data fragment update by xpath #3 - rest and service layers
[cps.git] / cps-service / src / test / groovy / org / onap / cps / api / impl / CpsDataServiceImplSpec.groovy
1 /*
2  * ============LICENSE_START=======================================================
3  *  Copyright (C) 2021 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
8  *
9  *        http://www.apache.org/licenses/LICENSE-2.0
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  *  SPDX-License-Identifier: Apache-2.0
17  *  ============LICENSE_END=========================================================
18  */
19
20 package org.onap.cps.api.impl
21
22 import org.onap.cps.TestUtils
23 import org.onap.cps.api.CpsAdminService
24 import org.onap.cps.api.CpsModuleService
25 import org.onap.cps.spi.CpsDataPersistenceService
26 import org.onap.cps.spi.FetchDescendantsOption
27 import org.onap.cps.spi.model.Anchor
28 import org.onap.cps.spi.model.DataNodeBuilder
29 import org.onap.cps.yang.YangTextSchemaSourceSet
30 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
31 import spock.lang.Specification
32 import spock.lang.Unroll
33
34 class CpsDataServiceImplSpec extends Specification {
35     def mockCpsDataPersistenceService = Mock(CpsDataPersistenceService)
36     def mockCpsAdminService = Mock(CpsAdminService)
37     def mockCpsModuleService = Mock(CpsModuleService)
38     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
39
40     def objectUnderTest = new CpsDataServiceImpl()
41
42     def setup() {
43         objectUnderTest.cpsDataPersistenceService = mockCpsDataPersistenceService
44         objectUnderTest.cpsAdminService = mockCpsAdminService
45         objectUnderTest.cpsModuleService = mockCpsModuleService
46         objectUnderTest.yangTextSchemaSourceSetCache = mockYangTextSchemaSourceSetCache
47     }
48
49     def dataspaceName = 'some dataspace'
50     def anchorName = 'some anchor'
51     def schemaSetName = 'some schema set'
52
53     def 'Saving json data.'() {
54         given: 'that the admin service will return an anchor'
55             def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
56             mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
57         and: 'the schema source set cache returns a schema source set'
58             def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
59             mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
60         and: 'the schema source sets returns the test-tree schema context'
61             def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
62             def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
63             mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
64         when: 'save data method is invoked with test-tree json data'
65             def jsonData = TestUtils.getResourceFileContent('test-tree.json')
66             objectUnderTest.saveData(dataspaceName, anchorName, jsonData)
67         then: 'the persistence service method is invoked with correct parameters'
68             1 * mockCpsDataPersistenceService.storeDataNode(dataspaceName, anchorName,
69                     { dataNode -> dataNode.xpath == '/test-tree' })
70     }
71
72     @Unroll
73     def 'Get data node with option #fetchDescendantsOption.'() {
74         def xpath = '/xpath'
75         def dataNode = new DataNodeBuilder().withXpath(xpath).build()
76         given: 'persistence service returns data for get data request'
77             mockCpsDataPersistenceService.getDataNode(dataspaceName, anchorName, xpath, fetchDescendantsOption) >> dataNode
78         expect: 'service returns same data if uses same parameters'
79             objectUnderTest.getDataNode(dataspaceName, anchorName, xpath, fetchDescendantsOption) == dataNode
80         where: 'all fetch options are supported'
81             fetchDescendantsOption << FetchDescendantsOption.values()
82     }
83
84     @Unroll
85     def 'Update data node leaves: #scenario.'() {
86         given: 'that the admin service will return an anchor'
87             def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
88             mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
89         and: 'the schema source set cache returns a schema source set'
90             def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
91             mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
92         and: 'the schema source sets returns the test-tree schema context'
93             def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
94             def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
95             mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
96         when: 'update data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
97             objectUnderTest.updateNodeLeaves(dataspaceName, anchorName, parentNodeXpath, jsonData)
98         then: 'the persistence service method is invoked with correct parameters'
99             1 * mockCpsDataPersistenceService.updateDataLeaves(dataspaceName, anchorName, nodeXpath, leaves)
100         where: 'following parameters were used'
101             scenario         | parentNodeXpath | jsonData                         | nodeXpath                           | leaves
102             'top level node' | '/'             | '{ "test-tree": {"branch": []}}' | '/test-tree'                        | Collections.emptyMap()
103             'level 2 node'   | '/test-tree'    | '{"branch": [{"name":"Name"}]}'  | '/test-tree/branch[@name=\'Name\']' | ['name': 'Name']
104     }
105
106     @Unroll
107     def 'Replace data node: #scenario.'() {
108         given: 'that the admin service will return an anchor'
109             def anchor = Anchor.builder().name(anchorName).schemaSetName(schemaSetName).build()
110             mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
111         and: 'the schema source set cache returns a schema source set'
112             def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
113             mockYangTextSchemaSourceSetCache.get(dataspaceName, schemaSetName) >> mockYangTextSchemaSourceSet
114         and: 'the schema source sets returns the test-tree schema context'
115             def yangResourceNameToContent = TestUtils.getYangResourcesAsMap('test-tree.yang')
116             def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourceNameToContent).getSchemaContext()
117             mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
118         when: 'replace data method is invoked with json data #jsonData and parent node xpath #parentNodeXpath'
119             objectUnderTest.replaceNodeTree(dataspaceName, anchorName, parentNodeXpath, jsonData)
120         then: 'the persistence service method is invoked with correct parameters'
121             1 * mockCpsDataPersistenceService.replaceDataNodeTree(dataspaceName, anchorName,
122                     { dataNode -> dataNode.xpath == nodeXpath })
123         where: 'following parameters were used'
124             scenario         | parentNodeXpath | jsonData                         | nodeXpath
125             'top level node' | '/'             | '{ "test-tree": {"branch": []}}' | '/test-tree'
126             'level 2 node'   | '/test-tree'    | '{"branch": [{"name":"Name"}]}'  | '/test-tree/branch[@name=\'Name\']'
127     }
128 }