diff options
author | Ruslan Kashapov <ruslan.kashapov@pantheon.tech> | 2021-02-08 11:02:39 +0200 |
---|---|---|
committer | Ruslan Kashapov <ruslan.kashapov@pantheon.tech> | 2021-02-16 14:06:40 +0200 |
commit | d1ea2af79952a41264552247441410fc24cd48f5 (patch) | |
tree | 5b11d435ff104c013d0ab5e5430d27fae630508d /cps-ri/src/test | |
parent | 10edcd916622acd3cb7069a069231153e715b467 (diff) |
Data fragment update by xpath #2 - persistence layer
Issue-ID: CPS-58
Change-Id: Ifc4580936d06c6907d6b5ab20657063b6707ccbe
Signed-off-by: Ruslan Kashapov <ruslan.kashapov@pantheon.tech>
Diffstat (limited to 'cps-ri/src/test')
-rw-r--r-- | cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy | 117 | ||||
-rw-r--r-- | cps-ri/src/test/resources/data/fragment.sql | 13 |
2 files changed, 118 insertions, 12 deletions
diff --git a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy index e3fa885301..a6e4701366 100644 --- a/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy +++ b/cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsDataPersistenceServiceSpec.groovy @@ -19,8 +19,14 @@ */ package org.onap.cps.spi.impl +import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS +import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS + import com.google.common.collect.ImmutableSet +import com.google.gson.Gson +import com.google.gson.GsonBuilder import org.onap.cps.spi.CpsDataPersistenceService +import org.onap.cps.spi.entities.FragmentEntity import org.onap.cps.spi.exceptions.AnchorNotFoundException import org.onap.cps.spi.exceptions.DataNodeNotFoundException import org.onap.cps.spi.exceptions.DataspaceNotFoundException @@ -31,28 +37,29 @@ import org.springframework.dao.DataIntegrityViolationException import org.springframework.test.context.jdbc.Sql import spock.lang.Unroll -import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS -import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS - class CpsDataPersistenceServiceSpec extends CpsPersistenceSpecBase { @Autowired CpsDataPersistenceService objectUnderTest + static final Gson GSON = new GsonBuilder().create() + static final String SET_DATA = '/data/fragment.sql' static final long ID_DATA_NODE_WITH_DESCENDANTS = 4001 static final String XPATH_DATA_NODE_WITH_DESCENDANTS = '/parent-1' static final String XPATH_DATA_NODE_WITH_LEAVES = '/parent-100' + static final long UPDATE_DATA_NODE_FRAGMENT_ID = 4202L + static final long UPDATE_DATA_NODE_SUB_FRAGMENT_ID = 4203L static final DataNode newDataNode = new DataNodeBuilder().build() static DataNode existingDataNode static DataNode existingChildDataNode - static Map<String, Map<String, Object>> expectedLeavesByXpathMap = [ - '/parent-100' : ["x": "y"], - '/parent-100/child-001' : ["a": "b", "c": ["d", "e", "f"]], - '/parent-100/child-002' : ["g": "h", "i": ["j", "k"]], - '/parent-100/child-002/grand-child': ["l": "m", "n": ["o", "p"]] + def expectedLeavesByXpathMap = [ + '/parent-100' : ['parent-leaf': 'parent-leaf-value'], + '/parent-100/child-001' : ['first-child-leaf': 'first-child-leaf-value'], + '/parent-100/child-002' : ['second-child-leaf': 'second-child-leaf-value'], + '/parent-100/child-002/grand-child': ['grand-child-leaf': 'grand-child-leaf-value'] ] static { @@ -201,4 +208,98 @@ class CpsDataPersistenceServiceSpec extends CpsPersistenceSpecBase { 'non-existing anchor' | DATASPACE_NAME | 'NO ANCHOR' | 'not relevant' || AnchorNotFoundException 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | 'NO XPATH' || DataNodeNotFoundException } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Update data node leaves.'() { + when: 'update is performed for leaves' + objectUnderTest.updateDataLeaves(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, + "/parent-200/child-201", ['leaf-value': 'new']) + then: 'leaves are updated for selected data node' + def updatedFragment = fragmentRepository.getOne(UPDATE_DATA_NODE_FRAGMENT_ID) + def updatedLeaves = getLeavesMap(updatedFragment) + assert updatedLeaves.size() == 1 + assert updatedLeaves.'leaf-value' == 'new' + and: 'existing child entry remains as is' + def childFragment = updatedFragment.getChildFragments().iterator().next() + def childLeaves = getLeavesMap(childFragment) + assert childFragment.getId() == UPDATE_DATA_NODE_SUB_FRAGMENT_ID + assert childLeaves.'leaf-value' == 'original' + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Update data leaves error scenario: #scenario.'() { + when: 'attempt to update data node for #scenario' + objectUnderTest.updateDataLeaves(dataspaceName, anchorName, xpath, ['leaf-name': 'leaf-value']) + then: 'a #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | anchorName | xpath || expectedException + 'non-existing dataspace' | 'NO DATASPACE' | 'not relevant' | 'not relevant' || DataspaceNotFoundException + 'non-existing anchor' | DATASPACE_NAME | 'NO ANCHOR' | 'not relevant' || AnchorNotFoundException + 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | 'NON-EXISTING XPATH' || DataNodeNotFoundException + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Replace data node tree with descendants removal.'() { + given: 'data node object with leaves updated, no children' + def submittedDataNode = buildDataNode("/parent-200/child-201", ['leaf-value': 'new'], []) + when: 'replace data node tree is performed' + objectUnderTest.replaceDataNodeTree(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, submittedDataNode) + then: 'leaves have been updated for selected data node' + def updatedFragment = fragmentRepository.getOne(UPDATE_DATA_NODE_FRAGMENT_ID) + def updatedLeaves = getLeavesMap(updatedFragment) + assert updatedLeaves.size() == 1 + assert updatedLeaves.'leaf-value' == 'new' + and: 'updated entry has no children' + updatedFragment.getChildFragments().isEmpty() + and: 'previously attached child entry is removed from database' + fragmentRepository.findById(UPDATE_DATA_NODE_SUB_FRAGMENT_ID).isEmpty() + } + + @Sql([CLEAR_DATA, SET_DATA]) + def 'Replace data node tree with descendants.'() { + given: 'data node object with leaves updated, having child with old content' + def submittedDataNode = buildDataNode("/parent-200/child-201", ['leaf-value': 'new'], [ + buildDataNode("/parent-200/child-201/grand-child", ['leaf-value': 'original'], []) + ]) + when: 'update is performed including descendants' + objectUnderTest.replaceDataNodeTree(DATASPACE_NAME, ANCHOR_FOR_DATA_NODES_WITH_LEAVES, submittedDataNode) + then: 'leaves have been updated for selected data node' + def updatedFragment = fragmentRepository.getOne(UPDATE_DATA_NODE_FRAGMENT_ID) + def updatedLeaves = getLeavesMap(updatedFragment) + assert updatedLeaves.size() == 1 + assert updatedLeaves.'leaf-value' == 'new' + and: 'previously attached child entry is removed from database' + fragmentRepository.findById(UPDATE_DATA_NODE_SUB_FRAGMENT_ID).isEmpty() + and: 'new child entry with same content is created' + def childFragment = updatedFragment.getChildFragments().iterator().next() + def childLeaves = getLeavesMap(childFragment) + assert childFragment.getId() != UPDATE_DATA_NODE_SUB_FRAGMENT_ID + assert childLeaves.'leaf-value' == 'original' + } + + @Unroll + @Sql([CLEAR_DATA, SET_DATA]) + def 'Replace data node tree error scenario: #scenario.'() { + given: 'data node object' + def submittedDataNode = buildDataNode(xpath, ['leaf-name':'leaf-value'], []) + when: 'attempt to update data node for #scenario' + objectUnderTest.replaceDataNodeTree(dataspaceName, anchorName, submittedDataNode) + then: 'a #expectedException is thrown' + thrown(expectedException) + where: 'the following data is used' + scenario | dataspaceName | anchorName | xpath || expectedException + 'non-existing dataspace' | 'NO DATASPACE' | 'not relevant' | 'not relevant' || DataspaceNotFoundException + 'non-existing anchor' | DATASPACE_NAME | 'NO ANCHOR' | 'not relevant' || AnchorNotFoundException + 'non-existing xpath' | DATASPACE_NAME | ANCHOR_FOR_DATA_NODES_WITH_LEAVES | 'NON-EXISTING XPATH' || DataNodeNotFoundException + } + + static DataNode buildDataNode(xpath, leaves, childDataNodes) { + return new DataNodeBuilder().withXpath(xpath).withLeaves(leaves).withChildDataNodes(childDataNodes).build() + } + + static Map<String, Object> getLeavesMap(FragmentEntity fragmentEntity) { + return GSON.fromJson(fragmentEntity.getAttributes(), Map<String, Object>.class) + } } diff --git a/cps-ri/src/test/resources/data/fragment.sql b/cps-ri/src/test/resources/data/fragment.sql index e652703268..95991462a3 100644 --- a/cps-ri/src/test/resources/data/fragment.sql +++ b/cps-ri/src/test/resources/data/fragment.sql @@ -17,7 +17,12 @@ INSERT INTO FRAGMENT (ID, XPATH, ANCHOR_ID, PARENT_ID, DATASPACE_ID) VALUES (4006, '/parent-1/child-1/grandchild-1', 3001, 4004, 1001); INSERT INTO FRAGMENT (ID, DATASPACE_ID, ANCHOR_ID, PARENT_ID, XPATH, ATTRIBUTES) VALUES - (4101, 1001, 3003, null, '/parent-100', '{"x": "y"}'), - (4102, 1001, 3003, 4101, '/parent-100/child-001', '{"a": "b", "c": ["d", "e", "f"]}'), - (4103, 1001, 3003, 4101, '/parent-100/child-002', '{"g": "h", "i": ["j", "k"]}'), - (4104, 1001, 3003, 4103, '/parent-100/child-002/grand-child', '{"l": "m", "n": ["o", "p"]}');
\ No newline at end of file + (4101, 1001, 3003, null, '/parent-100', '{"parent-leaf": "parent-leaf-value"}'), + (4102, 1001, 3003, 4101, '/parent-100/child-001', '{"first-child-leaf": "first-child-leaf-value"}'), + (4103, 1001, 3003, 4101, '/parent-100/child-002', '{"second-child-leaf": "second-child-leaf-value"}'), + (4104, 1001, 3003, 4103, '/parent-100/child-002/grand-child', '{"grand-child-leaf": "grand-child-leaf-value"}'); + +INSERT INTO FRAGMENT (ID, DATASPACE_ID, ANCHOR_ID, PARENT_ID, XPATH, ATTRIBUTES) VALUES + (4201, 1001, 3003, null, '/parent-200', '{"leaf-value": "original"}'), + (4202, 1001, 3003, 4201, '/parent-200/child-201', '{"leaf-value": "original"}'), + (4203, 1001, 3003, 4202, '/parent-200/child-201/grand-child', '{"leaf-value": "original"}');
\ No newline at end of file |