diff options
Diffstat (limited to 'v3po/data-impl/src/test/java/io/fd/honeycomb/v3po/data/impl/ModificationDiffTest.java')
-rw-r--r-- | v3po/data-impl/src/test/java/io/fd/honeycomb/v3po/data/impl/ModificationDiffTest.java | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/v3po/data-impl/src/test/java/io/fd/honeycomb/v3po/data/impl/ModificationDiffTest.java b/v3po/data-impl/src/test/java/io/fd/honeycomb/v3po/data/impl/ModificationDiffTest.java new file mode 100644 index 000000000..f5c270618 --- /dev/null +++ b/v3po/data-impl/src/test/java/io/fd/honeycomb/v3po/data/impl/ModificationDiffTest.java @@ -0,0 +1,376 @@ +package io.fd.honeycomb.v3po.data.impl; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Map; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateTip; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot; +import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException; +import org.opendaylight.yangtools.yang.data.api.schema.tree.TipProducingDataTree; +import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes; +import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException; +import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline; +import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl; + +public class ModificationDiffTest { + + private static final QName TOP_CONTAINER_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:test:diff", "2015-01-05", "top-container"); + private static final QName STRING_LEAF_QNAME = QName.create(TOP_CONTAINER_QNAME, "string"); + private static final QName NAME_LEAF_QNAME = QName.create(TOP_CONTAINER_QNAME, "name"); + private static final QName TEXT_LEAF_QNAME = QName.create(TOP_CONTAINER_QNAME, "text"); + private static final QName NESTED_LIST_QNAME = QName.create(TOP_CONTAINER_QNAME, "nested-list"); + private static final QName DEEP_LIST_QNAME = QName.create(TOP_CONTAINER_QNAME, "deep-list"); + + private YangInstanceIdentifier topContainerId = YangInstanceIdentifier.of(TOP_CONTAINER_QNAME);; + + @Test + public void testInitialWrite() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + final DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + final DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + final NormalizedNode<?, ?> topContainer = getTopContainer("string1"); + final YangInstanceIdentifier topContainerId = YangInstanceIdentifier.of(TOP_CONTAINER_QNAME); + dataTreeModification.write(topContainerId, topContainer); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + final DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertTrue(modificationDiff.getModificationsBefore().isEmpty()); + assertAfter(topContainer, topContainerId, modificationDiff); + } + + @Test + public void testUpdateWrite() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + final NormalizedNode<?, ?> topContainerBefore = addTopContainer(dataTree); + + final DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + final DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + final NormalizedNode<?, ?> topContainerAfter = getTopContainer("string2"); + dataTreeModification.write(topContainerId, topContainerAfter); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + final DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertBefore(topContainerBefore, topContainerId, modificationDiff); + assertAfter(topContainerAfter, topContainerId, modificationDiff); + } + + @Test + public void testUpdateMerge() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + final NormalizedNode<?, ?> topContainerBefore = addTopContainer(dataTree); + + final DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + final DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + final NormalizedNode<?, ?> topContainerAfter = getTopContainer("string2"); + dataTreeModification.merge(topContainerId, topContainerAfter); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + final DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertBefore(topContainerBefore, topContainerId, modificationDiff); + assertAfter(topContainerAfter, topContainerId, modificationDiff); + } + + @Test + public void testUpdateDelete() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + final NormalizedNode<?, ?> topContainerBefore = addTopContainer(dataTree); + + final DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + final DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + dataTreeModification.delete(topContainerId); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + final DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertBefore(topContainerBefore, topContainerId, modificationDiff); + assertTrue(modificationDiff.getModificationsAfter().isEmpty()); + } + + @Test + public void testWriteAndUpdateInnerList() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + addTopContainer(dataTree); + + DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + final YangInstanceIdentifier listId = + YangInstanceIdentifier.create( + new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME), + new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME)); + + final MapNode mapNode = getNestedList("name1", "text"); + dataTreeModification.write(listId, mapNode); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertTrue(modificationDiff.getModificationsBefore().isEmpty()); + assertAfter(mapNode, listId, modificationDiff); + + // Commit so that update can be tested next + dataTree.commit(prepare); + + YangInstanceIdentifier listItemId = listId.node( + new YangInstanceIdentifier.NodeIdentifierWithPredicates(NESTED_LIST_QNAME, NAME_LEAF_QNAME, "name1")); + MapEntryNode mapEntryNode = + getNestedList("name1", "text-update").getValue().iterator().next(); + + dataTreeSnapshot = dataTree.takeSnapshot(); + dataTreeModification = dataTreeSnapshot.newModification(); + dataTreeModification.write(listItemId, mapEntryNode); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + prepare = dataTree.prepare(dataTreeModification); + + modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertBefore(mapNode.getValue().iterator().next(), listItemId, modificationDiff); + assertAfter(mapEntryNode, listItemId, modificationDiff); + } + + @Test + public void testWriteTopContainerAndInnerList() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + + DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + + final ContainerNode topContainer = getTopContainer("string1"); + dataTreeModification.write(topContainerId, topContainer); + + final YangInstanceIdentifier listId = + YangInstanceIdentifier.create( + new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME), + new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME)); + + final MapNode mapNode = getNestedList("name1", "text"); + dataTreeModification.write(listId, mapNode); + + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + final DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertTrue(modificationDiff.getModificationsBefore().isEmpty()); + + // TODO HONEYCOMB-94 2 after modifications should appear, for top-container and nested-list entry + assertAfter(Builders.containerBuilder(topContainer) + .withChild(mapNode) + .build(), + topContainerId, modificationDiff); + } + + @Test + public void testWriteDeepList() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + addTopContainer(dataTree); + + DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + + YangInstanceIdentifier listId = + YangInstanceIdentifier.create( + new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME), + new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME)); + + MapNode mapNode = getNestedList("name1", "text"); + dataTreeModification.write(listId, mapNode); + + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + dataTree.commit(prepare); + + dataTreeSnapshot = dataTree.takeSnapshot(); + dataTreeModification = dataTreeSnapshot.newModification(); + + final YangInstanceIdentifier.NodeIdentifierWithPredicates nestedListNodeId = + new YangInstanceIdentifier.NodeIdentifierWithPredicates(NESTED_LIST_QNAME, NAME_LEAF_QNAME, "name1"); + listId = YangInstanceIdentifier.create( + new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME), + new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME), + nestedListNodeId); + final YangInstanceIdentifier deepListId = listId.node(new YangInstanceIdentifier.NodeIdentifier(DEEP_LIST_QNAME)); + final YangInstanceIdentifier deepListEntryId = deepListId.node( + new YangInstanceIdentifier.NodeIdentifierWithPredicates(DEEP_LIST_QNAME, NAME_LEAF_QNAME,"name1")); + + final MapEntryNode deepListEntry = getDeepList("name1").getValue().iterator().next(); + // Merge parent list, just to see no modifications on it + dataTreeModification.merge( + listId, + Builders.mapEntryBuilder().withNodeIdentifier(nestedListNodeId).withChild(ImmutableNodes.leafNode(NAME_LEAF_QNAME, "name1")).build()); + dataTreeModification.merge( + deepListId, + Builders.mapBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(DEEP_LIST_QNAME)).build()); + dataTreeModification.merge( + deepListEntryId, + deepListEntry); + + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + prepare = dataTree.prepare(dataTreeModification); + dataTree.commit(prepare); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertTrue(modificationDiff.getModificationsBefore().isEmpty()); + assertAfter(getDeepList("name1"), deepListId, modificationDiff); + } + + @Test + public void testDeleteInnerListItem() throws Exception { + final TipProducingDataTree dataTree = getDataTree(); + addTopContainer(dataTree); + + DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + final YangInstanceIdentifier listId = + YangInstanceIdentifier.create( + new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME), + new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME)); + + final MapNode mapNode = getNestedList("name1", "text"); + dataTreeModification.write(listId, mapNode); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + + // Commit so that update can be tested next + dataTree.commit(prepare); + + YangInstanceIdentifier listItemId = listId.node( + new YangInstanceIdentifier.NodeIdentifierWithPredicates(NESTED_LIST_QNAME, NAME_LEAF_QNAME, "name1")); + + dataTreeSnapshot = dataTree.takeSnapshot(); + dataTreeModification = dataTreeSnapshot.newModification(); + dataTreeModification.delete(listItemId); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + prepare = dataTree.prepare(dataTreeModification); + + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff = + ModifiableDataTreeDelegator.ModificationDiff + .recursivelyFromCandidate(YangInstanceIdentifier.EMPTY, prepare.getRootNode()); + + assertBefore(mapNode.getValue().iterator().next(), listItemId, modificationDiff); + assertTrue(modificationDiff.getModificationsAfter().isEmpty()); + } + + private NormalizedNode<?, ?> addTopContainer(final TipProducingDataTree dataTree) throws DataValidationFailedException { + DataTreeSnapshot dataTreeSnapshot = dataTree.takeSnapshot(); + DataTreeModification dataTreeModification = dataTreeSnapshot.newModification(); + final NormalizedNode<?, ?> topContainerBefore = getTopContainer("string1"); + dataTreeModification.write(topContainerId, topContainerBefore); + dataTreeModification.ready(); + dataTree.validate(dataTreeModification); + DataTreeCandidateTip prepare = dataTree.prepare(dataTreeModification); + dataTree.commit(prepare); + return topContainerBefore; + } + + private void assertAfter(final NormalizedNode<?, ?> topContainer, final YangInstanceIdentifier topContainerId, + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff) { + assertModification(topContainer, topContainerId, modificationDiff.getModificationsAfter()); + } + + private void assertModification(final NormalizedNode<?, ?> topContainer, + final YangInstanceIdentifier topContainerId, + final Map<YangInstanceIdentifier, NormalizedNode<?, ?>> modificationMap) { + assertEquals(1, modificationMap.keySet().size()); + assertEquals(topContainerId, modificationMap.keySet().iterator().next()); + assertEquals(topContainer, modificationMap.values().iterator().next()); + } + + private void assertBefore(final NormalizedNode<?, ?> topContainerBefore, + final YangInstanceIdentifier topContainerId, + final ModifiableDataTreeDelegator.ModificationDiff modificationDiff) { + assertModification(topContainerBefore, topContainerId, modificationDiff.getModificationsBefore()); + } + + private TipProducingDataTree getDataTree() throws ReactorException { + final TipProducingDataTree dataTree = InMemoryDataTreeFactory.getInstance().create(TreeType.CONFIGURATION); + dataTree.setSchemaContext(getSchemaCtx()); + return dataTree; + } + + private ContainerNode getTopContainer(final String stringValue) { + return Builders.containerBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_QNAME)) + .withChild(ImmutableNodes.leafNode(STRING_LEAF_QNAME, stringValue)) + .build(); + } + + private MapNode getNestedList(final String listItemName, final String text) { + return Builders.mapBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME)) + .withChild( + Builders.mapEntryBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(NESTED_LIST_QNAME, NAME_LEAF_QNAME, listItemName)) + .withChild(ImmutableNodes.leafNode(NAME_LEAF_QNAME, listItemName)) + .withChild(ImmutableNodes.leafNode(TEXT_LEAF_QNAME, text)) + .build() + ) + .build(); + } + + private MapNode getDeepList(final String listItemName) { + return Builders.mapBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(DEEP_LIST_QNAME)) + .withChild( + Builders.mapEntryBuilder() + .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(DEEP_LIST_QNAME, NAME_LEAF_QNAME, listItemName)) + .withChild(ImmutableNodes.leafNode(NAME_LEAF_QNAME, listItemName)) + .build() + ) + .build(); + } + + private SchemaContext getSchemaCtx() throws ReactorException { + final CrossSourceStatementReactor.BuildAction buildAction = YangInferencePipeline.RFC6020_REACTOR.newBuild(); + buildAction.addSource(new YangStatementSourceImpl(getClass().getResourceAsStream("/test-diff.yang"))); + return buildAction.buildEffective(); + } +}
\ No newline at end of file |