From 885980d8ebf6bc8be9efad7ce9094deeb602a076 Mon Sep 17 00:00:00 2001 From: Arpit Singh Date: Tue, 21 Nov 2023 21:01:43 +0530 Subject: CPS Delta API: Update action for delta service - Added code for Update action in Delta service - added method to get updated Leaf data: getUpdatedLeavesBetweenSourceAndTargetDataNode - added method to compare Leaf data common in source and target data node - added method to process leaves unique to target data node - added method to compare leaves: compareLeaves - added method to store updated data to a DeltaReport: addUpdatedLeavesToDeltaReport - Added corresponding testware Issue-ID: CPS-1824 Signed-off-by: Arpit Singh Change-Id: I3de07ea3227988784a0892f6a92c238ecf00a7fa --- .../CpsDataServiceIntegrationSpec.groovy | 100 +++++++++++++++------ .../bookstore/bookstoreDataForDeltaReport.json | 5 +- 2 files changed, 76 insertions(+), 29 deletions(-) (limited to 'integration-test') diff --git a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy index e14309994..3843a9f1b 100644 --- a/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy +++ b/integration-test/src/test/groovy/org/onap/cps/integration/functional/CpsDataServiceIntegrationSpec.groovy @@ -431,40 +431,30 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { def 'Get delta between 2 anchors for when #scenario'() { when: 'attempt to get delta report between anchors' - def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, xpath, fetchDescendantOption) + def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, '/', OMIT_DESCENDANTS) then: 'delta report contains expected number of changes' - result.size() == 2 - and: 'delta report contains expected action' - assert result.get(index).getAction() == expectedActions - and: 'delta report contains expected xpath' - assert result.get(index).getXpath() == expectedXpath - where: 'following data was used' - scenario | index | xpath || expectedActions || expectedXpath | fetchDescendantOption - 'a node is removed' | 0 | '/' || 'remove' || "/bookstore-address[@bookstore-name='Easons-1']" | OMIT_DESCENDANTS - 'a node is added' | 1 | '/' || 'add' || "/bookstore-address[@bookstore-name='Crossword Bookstores']" | OMIT_DESCENDANTS - } - - def 'Get delta between 2 anchors where child nodes are added/removed but parent node remains unchanged'() { - def parentNodeXpath = "/bookstore" - when: 'attempt to get delta report between anchors' - def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, parentNodeXpath, INCLUDE_ALL_DESCENDANTS) - then: 'delta report contains expected number of changes' - result.size() == 11 - and: 'the delta report does not contain parent node xpath' - def xpaths = getDeltaReportEntities(result).get('xpaths') - assert !(xpaths.contains(parentNodeXpath)) + result.size() == 3 + and: 'delta report contains UPDATE action with expected xpath' + assert result[0].getAction() == 'update' + assert result[0].getXpath() == '/bookstore' + and: 'delta report contains REMOVE action with expected xpath' + assert result[1].getAction() == 'remove' + assert result[1].getXpath() == "/bookstore-address[@bookstore-name='Easons-1']" + and: 'delta report contains ADD action with expected xpath' + assert result[2].getAction() == 'add' + assert result[2].getXpath() == "/bookstore-address[@bookstore-name='Crossword Bookstores']" } def 'Get delta between 2 anchors returns empty response when #scenario'() { when: 'attempt to get delta report between anchors' - def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, sourceAnchor, targetAnchor, xpath, INCLUDE_ALL_DESCENDANTS) + def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, targetAnchor, xpath, INCLUDE_ALL_DESCENDANTS) then: 'delta report is empty' assert result.isEmpty() where: 'following data was used' - scenario | sourceAnchor | targetAnchor | xpath - 'anchors with identical data are queried' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_4 | '/' - 'same anchor name is passed as parameter' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_3 | '/' - 'non existing xpath' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_5 | '/non-existing-xpath' + scenario | targetAnchor | xpath + 'anchors with identical data are queried' | BOOKSTORE_ANCHOR_4 | '/' + 'same anchor name is passed as parameter' | BOOKSTORE_ANCHOR_3 | '/' + 'non existing xpath' | BOOKSTORE_ANCHOR_5 | '/non-existing-xpath' } def 'Get delta between anchors error scenario: #scenario'() { @@ -511,6 +501,64 @@ class CpsDataServiceIntegrationSpec extends FunctionalSpecBase { 'is empty' | "/bookstore/container-without-leaves" } + def 'Get delta between anchors when leaves of existing data nodes are updated,: #scenario'() { + when: 'attempt to get delta between leaves of existing data nodes' + def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, sourceAnchor, targetAnchor, xpath, OMIT_DESCENDANTS) + then: 'expected action is update' + assert result[0].getAction() == 'update' + and: 'the payload has expected leaf values' + def sourceData = result[0].getSourceData() + def targetData = result[0].getTargetData() + assert sourceData == expectedSourceValue + assert targetData == expectedTargetValue + where: 'following data was used' + scenario | sourceAnchor | targetAnchor | xpath || expectedSourceValue | expectedTargetValue + 'leaf is updated in target anchor' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_5 | '/bookstore' || ['bookstore-name': 'Easons-1'] | ['bookstore-name': 'Crossword Bookstores'] + 'leaf is removed in target anchor' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_5 | "/bookstore/categories[@code='5']/books[@title='Book 1']" || [price:1] | null + 'leaf is added in target anchor' | BOOKSTORE_ANCHOR_5 | BOOKSTORE_ANCHOR_3 | "/bookstore/categories[@code='5']/books[@title='Book 1']" || null | [price:1] + } + + def 'Get delta between anchors when child data nodes under existing parent data nodes are updated: #scenario'() { + when: 'attempt to get delta between leaves of existing data nodes' + def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, sourceAnchor, targetAnchor, xpath, DIRECT_CHILDREN_ONLY) + then: 'expected action is update' + assert result[0].getAction() == 'update' + and: 'the delta report has expected child node xpaths' + def deltaReportEntities = getDeltaReportEntities(result) + def childNodeXpathsInDeltaReport = deltaReportEntities.get('xpaths') + assert childNodeXpathsInDeltaReport.contains(expectedChildNodeXpath) + where: 'following data was used' + scenario | sourceAnchor | targetAnchor | xpath || expectedChildNodeXpath + 'source and target anchors have child data nodes' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_5 | '/bookstore/premises' || '/bookstore/premises/addresses[@house-number=\'2\' and @street=\'Main Street\']' + 'removed child data nodes in target anchor' | BOOKSTORE_ANCHOR_5 | BOOKSTORE_ANCHOR_3 | '/bookstore' || '/bookstore/support-info' + 'added child data nodes in target anchor' | BOOKSTORE_ANCHOR_3 | BOOKSTORE_ANCHOR_5 | '/bookstore' || '/bookstore/support-info' + } + + def 'Get delta between anchors where source and target data nodes have leaves and child data nodes'() { + given: 'parent node xpath and expected data in delta report' + def parentNodeXpath = "/bookstore/categories[@code='1']" + def expectedSourceDataInParentNode = ['name':'Children'] + def expectedTargetDataInParentNode = ['name':'Kids'] + def expectedSourceDataInChildNode = [['lang' : 'English'],['price':20, 'editions':[1988, 2000]]] + def expectedTargetDataInChildNode = [['lang':'English/German'], ['price':200, 'editions':[2023, 1988, 2000]]] + when: 'attempt to get delta between leaves of existing data nodes' + def result = objectUnderTest.getDeltaByDataspaceAndAnchors(FUNCTIONAL_TEST_DATASPACE_3, BOOKSTORE_ANCHOR_3, BOOKSTORE_ANCHOR_5, parentNodeXpath, INCLUDE_ALL_DESCENDANTS) + def deltaReportEntities = getDeltaReportEntities(result) + then: 'expected action is update' + assert result[0].getAction() == 'update' + and: 'the payload has expected parent node xpath' + assert deltaReportEntities.get('xpaths').contains(parentNodeXpath) + and: 'delta report has expected source and target data' + assert deltaReportEntities.get('sourcePayload').contains(expectedSourceDataInParentNode) + assert deltaReportEntities.get('targetPayload').contains(expectedTargetDataInParentNode) + and: 'the delta report also has expected child node xpaths' + assert deltaReportEntities.get('xpaths').containsAll(["/bookstore/categories[@code='1']/books[@title='The Gruffalo']", "/bookstore/categories[@code='1']/books[@title='Matilda']"]) + and: 'the delta report also has expected source and target data of child nodes' + assert deltaReportEntities.get('sourcePayload').containsAll(expectedSourceDataInChildNode) + assert deltaReportEntities.get('targetPayload').containsAll(expectedTargetDataInChildNode) + + } + def getDeltaReportEntities(List deltaReport) { def xpaths = [] def action = [] diff --git a/integration-test/src/test/resources/data/bookstore/bookstoreDataForDeltaReport.json b/integration-test/src/test/resources/data/bookstore/bookstoreDataForDeltaReport.json index 73b84fc98..1dd6c0d41 100644 --- a/integration-test/src/test/resources/data/bookstore/bookstoreDataForDeltaReport.json +++ b/integration-test/src/test/resources/data/bookstore/bookstoreDataForDeltaReport.json @@ -7,7 +7,7 @@ } ], "bookstore": { - "bookstore-name": "Easons", + "bookstore-name": "Crossword Bookstores", "premises": { "addresses": [ { @@ -96,8 +96,7 @@ "title": "Book 1", "lang": "blah", "authors": [], - "editions": [], - "price": 1 + "editions": [] }, { "title": "Book 2", -- cgit 1.2.3-korg