aboutsummaryrefslogtreecommitdiffstats
path: root/cps-service/src/test/groovy/org/onap
diff options
context:
space:
mode:
authorArpit Singh <as00745003@techmahindra.com>2023-09-07 17:05:37 +0530
committerArpit Singh <as00745003@techmahindra.com>2024-06-06 14:13:32 +0530
commitd7fa9601a1409ee3a156ac2f6a6ec11853989cd7 (patch)
tree1967c1bebdfca2e116bdd6acf630d87e39ccf3ae /cps-service/src/test/groovy/org/onap
parentf8ca09bf4e5d76fb95bd1eda17f15a7fd92d0f63 (diff)
CPS Delta API 2: Delta between anchor and payload
- Second API to get Delta between an anchor and JSON payload - added new API getDeltaByDataspaceAnchorAndPayload - added controller and service layer methods getDeltaByDataspaceAnchorAndPayload - Core Delta algorithm remains same as the first API. getDeltaByDataspaceAnchorAndPayload will call getDeltaBetweenDataNodes Issue-ID: CPS-1836 Signed-off-by: Arpit Singh <as00745003@techmahindra.com> Change-Id: Id74cd930ce48e5cb414aa62c5381b79675788a37
Diffstat (limited to 'cps-service/src/test/groovy/org/onap')
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy74
-rwxr-xr-xcps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy11
-rw-r--r--cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy19
3 files changed, 98 insertions, 6 deletions
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
index 4542ecb67..edf25715b 100644
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
@@ -23,6 +23,7 @@
package org.onap.cps.api.impl
+import com.fasterxml.jackson.databind.ObjectMapper
import ch.qos.logback.classic.Level
import ch.qos.logback.classic.Logger
import ch.qos.logback.core.read.ListAppender
@@ -43,6 +44,9 @@ import org.onap.cps.spi.utils.CpsValidator
import org.onap.cps.utils.ContentType
import org.onap.cps.utils.YangParser
import org.onap.cps.utils.YangParserHelper
+import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.PrefixResolver
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
import org.onap.cps.yang.YangTextSchemaSourceSet
import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
import org.slf4j.LoggerFactory
@@ -56,11 +60,15 @@ class CpsDataServiceImplSpec extends Specification {
def mockCpsAnchorService = Mock(CpsAnchorService)
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
def mockCpsValidator = Mock(CpsValidator)
- def yangParser = new YangParser(new YangParserHelper(), mockYangTextSchemaSourceSetCache)
+ def mockTimedYangTextSchemaSourceSetBuilder = Mock(TimedYangTextSchemaSourceSetBuilder)
+ def yangParser = new YangParser(new YangParserHelper(), mockYangTextSchemaSourceSetCache, mockTimedYangTextSchemaSourceSetBuilder)
def mockCpsDeltaService = Mock(CpsDeltaService);
def mockDataUpdateEventsService = Mock(CpsDataUpdateEventsService)
+ def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ def mockPrefixResolver = Mock(PrefixResolver)
- def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockDataUpdateEventsService, mockCpsAnchorService, mockCpsValidator, yangParser, mockCpsDeltaService)
+ def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockDataUpdateEventsService, mockCpsAnchorService,
+ mockCpsValidator, yangParser, mockCpsDeltaService, jsonObjectMapper, mockPrefixResolver)
def logger = (Logger) LoggerFactory.getLogger(objectUnderTest.class)
def loggingListAppender
@@ -230,6 +238,60 @@ class CpsDataServiceImplSpec extends Specification {
1 * mockCpsDeltaService.getDeltaReports(sourceDataNodes, targetDataNodes)
}
+ def 'Get delta between anchor and payload with user provided schema #scenario'() {
+ given: 'user provided schema set '
+ def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
+ setupSchemaSetMocksForDelta(yangResourcesNameToContentMap)
+ when: 'attempt to get delta between an anchor and a JSON payload'
+ objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, yangResourcesNameToContentMap, jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+ then: 'dataspacename and anchor names are validated'
+ 1 * mockCpsValidator.validateNameCharacters(['some-dataspace', 'some-anchor'])
+ and: 'source data nodes are fetched using appropriate persistence layer method'
+ 1 * mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> sourceDataNodes
+ and: 'appropriate delta service method is invoked once with correct source and target data nodes'
+ 1 * mockCpsDeltaService.getDeltaReports({sourceDataNodesRebuilt -> sourceDataNodesRebuilt.xpath[0] == expectedNodeXpath}, {targetDataNodes -> targetDataNodes.xpath[0] == expectedNodeXpath})
+ where: 'following data was used'
+ scenario | xpath | sourceDataNodes | jsonData || expectedNodeXpath
+ 'root node xpath' | '/' | [new DataNodeBuilder().withXpath('/bookstore').build()] | '{"bookstore":{"bookstore-name":"Easons"}}' || '/bookstore'
+ 'parent xpath' | '/bookstore' | [new DataNodeBuilder().withXpath('/bookstore').build()] | '{"bookstore":{"bookstore-name":"Easons"}}' || '/bookstore'
+ 'non-root xpath' | '/bookstore/categories[@code="02"]' | [new DataNodeBuilder().withXpath('/bookstore/categories[@code="02"]').withLeaves(["code":"02"]).build()] | '{"categories":[{"name":"kids","code":"02"}]}' || '/bookstore/categories[@code=\'02\']'
+ }
+
+ def 'Get delta between anchor and payload by using schema from anchor #scenario'() {
+ given: 'schema set for a given dataspace and anchor'
+ setupSchemaSetMocks("bookstore.yang")
+ when: 'attempt to get delta between an anchor and a JSON payload'
+ objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, [:], jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+ then: 'dataspacename and anchor names are validated'
+ 1 * mockCpsValidator.validateNameCharacters(['some-dataspace', 'some-anchor'])
+ and: 'source data nodes are fetched using appropriate persistence layer method'
+ 1 * mockCpsDataPersistenceService.getDataNodes(dataspaceName, anchorName, xpath, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) >> sourceDataNodes
+ and: 'appropriate delta service method is invoked once with correct source and target data nodes'
+ 1 * mockCpsDeltaService.getDeltaReports({sourceDataNodesRebuilt -> sourceDataNodesRebuilt.xpath[0] == expectedNodeXpath}, {targetDataNodes -> targetDataNodes.xpath[0] == expectedNodeXpath})
+ where: 'following data was used'
+ scenario | xpath | sourceDataNodes | jsonData || expectedNodeXpath
+ 'root node xpath' | '/' | [new DataNodeBuilder().withXpath('/bookstore').build()] | '{"bookstore":{"bookstore-name":"Easons"}}' || '/bookstore'
+ 'parent xpath' | '/bookstore' | [new DataNodeBuilder().withXpath('/bookstore').build()] | '{"bookstore":{"bookstore-name":"Easons"}}' || '/bookstore'
+ 'non-root xpath' | '/bookstore/categories[@code="02"]' | [new DataNodeBuilder().withXpath('/bookstore/categories[@code="02"]').withLeaves(["code":"02"]).build()] | '{"categories":[{"name":"kids","code":"02"}]}' || '/bookstore/categories[@code=\'02\']'
+ }
+
+ def 'Delta between anchor and payload error scenario #scenario'() {
+ given: 'schema set for given anchor and dataspace references bookstore model'
+ def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
+ setupSchemaSetMocksForDelta(yangResourcesNameToContentMap)
+ when: 'attempt to get delta between anchor and payload'
+ objectUnderTest.getDeltaByDataspaceAnchorAndPayload(dataspaceName, anchorName, xpath, yangResourcesNameToContentMap, jsonData, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS)
+ then: 'expected exception is thrown'
+ thrown(DataValidationException)
+ where: 'following parameters were used'
+ scenario | xpath | jsonData
+ 'invalid json data with root node xpath' | '/' | '{"some-key": "some-value"'
+ 'empty json data with root node xpath' | '/' | '{}'
+ 'invalid json data with parent node xpath' | '/bookstore' | '{"some-key": "some-value"'
+ 'empty json data with parent node xpath' | '/bookstore' | '{}'
+ 'empty json data with xpath' | "/bookstore/categories[@code='02']" | '{}'
+ }
+
def 'Update data node leaves: #scenario.'() {
given: 'schema set for given anchor and dataspace references test-tree model'
setupSchemaSetMocks('test-tree.yang')
@@ -503,4 +565,12 @@ class CpsDataServiceImplSpec extends Specification {
mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
}
+ def setupSchemaSetMocksForDelta(Map<String, String> yangResourcesNameToContentMap) {
+ def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
+ mockTimedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap) >> mockYangTextSchemaSourceSet
+ mockYangTextSchemaSourceSetCache.get(_, _) >> mockYangTextSchemaSourceSet
+ def schemaContext = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap).getSchemaContext()
+ mockYangTextSchemaSourceSet.getSchemaContext() >> schemaContext
+ }
+
}
diff --git a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
index 57f2f8ea7..9e55e8f10 100755
--- a/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
@@ -23,6 +23,7 @@
package org.onap.cps.api.impl
+import com.fasterxml.jackson.databind.ObjectMapper
import org.onap.cps.TestUtils
import org.onap.cps.api.CpsAnchorService
import org.onap.cps.api.CpsDeltaService
@@ -31,6 +32,8 @@ import org.onap.cps.spi.CpsDataPersistenceService
import org.onap.cps.spi.CpsModulePersistenceService
import org.onap.cps.spi.model.Anchor
import org.onap.cps.spi.utils.CpsValidator
+import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.PrefixResolver
import org.onap.cps.utils.ContentType
import org.onap.cps.utils.YangParser
import org.onap.cps.utils.YangParserHelper
@@ -45,15 +48,17 @@ class E2ENetworkSliceSpec extends Specification {
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
def mockCpsValidator = Mock(CpsValidator)
def timedYangTextSchemaSourceSetBuilder = new TimedYangTextSchemaSourceSetBuilder()
- def yangParser = new YangParser(new YangParserHelper(), mockYangTextSchemaSourceSetCache)
+ def yangParser = new YangParser(new YangParserHelper(), mockYangTextSchemaSourceSetCache, timedYangTextSchemaSourceSetBuilder)
def mockCpsDeltaService = Mock(CpsDeltaService)
+ def jsonObjectMapper = new JsonObjectMapper(new ObjectMapper())
+ def mockPrefixResolver = Mock(PrefixResolver)
def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,
mockYangTextSchemaSourceSetCache, mockCpsAnchorService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)
def mockDataUpdateEventsService = Mock(CpsDataUpdateEventsService)
- def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockDataUpdateEventsService, mockCpsAnchorService, mockCpsValidator, yangParser, mockCpsDeltaService)
-
+ def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockDataUpdateEventsService, mockCpsAnchorService, mockCpsValidator,
+ yangParser, mockCpsDeltaService, jsonObjectMapper, mockPrefixResolver)
def dataspaceName = 'someDataspace'
def anchorName = 'someAnchor'
def schemaSetName = 'someSchemaSet'
diff --git a/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy b/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy
index 99070fe72..18d0502e3 100644
--- a/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy
+++ b/cps-service/src/test/groovy/org/onap/cps/utils/YangParserSpec.groovy
@@ -1,6 +1,7 @@
/*
* ============LICENSE_START=======================================================
* Copyright (C) 2024 Nordix Foundation
+ * Modifications Copyright (C) 2024 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,9 +21,12 @@
package org.onap.cps.utils
+import org.onap.cps.TestUtils
import org.onap.cps.spi.exceptions.DataValidationException
import org.onap.cps.spi.model.Anchor
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
import org.onap.cps.yang.YangTextSchemaSourceSet
+import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode
import org.opendaylight.yangtools.yang.model.api.SchemaContext
import spock.lang.Specification
@@ -32,10 +36,12 @@ class YangParserSpec extends Specification {
def mockYangParserHelper = Mock(YangParserHelper)
def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
+ def mockTimedYangTextSchemaSourceSetBuilder = Mock(TimedYangTextSchemaSourceSetBuilder)
- def objectUnderTest = new YangParser(mockYangParserHelper, mockYangTextSchemaSourceSetCache)
+ def objectUnderTest = new YangParser(mockYangParserHelper, mockYangTextSchemaSourceSetCache, mockTimedYangTextSchemaSourceSetBuilder)
def anchor = new Anchor(dataspaceName: 'my dataspace', schemaSetName: 'my schema')
+ def yangResourcesNameToContentMap = TestUtils.getYangResourcesAsMap('bookstore.yang')
def mockYangTextSchemaSourceSet = Mock(YangTextSchemaSourceSet)
def mockSchemaContext = Mock(SchemaContext)
def containerNodeFromYangUtils = Mock(ContainerNode)
@@ -82,4 +88,15 @@ class YangParserSpec extends Specification {
1 * mockYangTextSchemaSourceSetCache.removeFromCache('my dataspace', 'my schema')
}
+ def 'Parsing data with yang resource to context map.'() {
+ given: 'the schema source set for the yang resource map is returned'
+ mockTimedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap) >> mockYangTextSchemaSourceSet
+ when: 'parsing some json data'
+ def result = objectUnderTest.parseData(ContentType.JSON, 'some json', yangResourcesNameToContentMap, noParent)
+ then: 'the yang parser helper always returns a container node'
+ 1 * mockYangParserHelper.parseData(ContentType.JSON, 'some json', mockSchemaContext, noParent) >> containerNodeFromYangUtils
+ and: 'the result is the same container node as return from yang utils'
+ assert result == containerNodeFromYangUtils
+ }
+
}