Adjust to yangtools-2.0.0 changes
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / utils / PruningDataTreeModificationTest.java
index 19460576684ee75c61a5cc1f08486e225216ec0d..18949ac21ecd5ec3d491933b9f15e0041a8f79fe 100644 (file)
 
 package org.opendaylight.controller.cluster.datastore.utils;
 
 
 package org.opendaylight.controller.cluster.datastore.utils;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import java.net.URI;
-import java.util.Set;
+import static org.opendaylight.controller.md.cluster.datastore.model.CompositeModel.AUG_CONTAINER;
+import static org.opendaylight.controller.md.cluster.datastore.model.CompositeModel.AUG_INNER_CONTAINER;
+import static org.opendaylight.controller.md.cluster.datastore.model.CompositeModel.AUG_QNAME;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.NAME_QNAME;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.TEST_QNAME;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.innerNode;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNode;
+import static org.opendaylight.controller.md.cluster.datastore.model.TestModel.outerNodeEntry;
+
+import com.google.common.reflect.Reflection;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Optional;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.cluster.datastore.Shard;
+import org.opendaylight.controller.cluster.datastore.ShardDataTree;
 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
 import org.opendaylight.controller.md.cluster.datastore.model.CarsModel;
+import org.opendaylight.controller.md.cluster.datastore.model.PeopleModel;
+import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
+import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 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.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModificationCursor;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.TreeType;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.tree.InMemoryDataTreeFactory;
 import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
 import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 
 public class PruningDataTreeModificationTest {
 
 public class PruningDataTreeModificationTest {
+    static final SchemaContext SCHEMA_CONTEXT = SchemaContextHelper.select(SchemaContextHelper.CARS_YANG,
+            SchemaContextHelper.ODL_DATASTORE_TEST_YANG);
 
 
-    @Mock
-    DataTreeModification delegate;
-
-    @Mock
-    Set<URI> validNamespaces;
+    static final QName INVALID_TEST_QNAME = QName.create(TestModel.TEST_QNAME, "invalid");
+    static final YangInstanceIdentifier INVALID_TEST_PATH = YangInstanceIdentifier.of(INVALID_TEST_QNAME);
 
     @Mock
 
     @Mock
-    NormalizedNode<?,?> prunedNormalizedNode;
+    private DataTreeModification mockModification;
 
 
-    PruningDataTreeModification pruningDataTreeModification;
+    private DataTree dataTree;
+    private DataTreeModification realModification;
+    private DataTreeModification proxyModification;
+    private PruningDataTreeModification pruningDataTreeModification;
 
     @Before
 
     @Before
-    public void setUp(){
+    @SuppressWarnings("checkstyle:avoidHidingCauseException")
+    public void setUp() {
         MockitoAnnotations.initMocks(this);
         MockitoAnnotations.initMocks(this);
-        pruningDataTreeModification = new PruningDataTreeModification(delegate, validNamespaces) {
-            @Override
-            NormalizedNode<?, ?> pruneNormalizedNode(NormalizedNode<?, ?> input) {
-                return prunedNormalizedNode;
+
+        dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION,
+            SCHEMA_CONTEXT);
+
+        realModification = dataTree.takeSnapshot().newModification();
+        proxyModification = Reflection.newProxy(DataTreeModification.class, (proxy, method, args) -> {
+            try {
+                method.invoke(mockModification, args);
+                return method.invoke(realModification, args);
+            } catch (InvocationTargetException e) {
+                throw e.getCause();
             }
             }
-        };
+        });
+
+        pruningDataTreeModification = new PruningDataTreeModification(proxyModification, dataTree, SCHEMA_CONTEXT);
     }
 
     @Test
     }
 
     @Test
-    public void testDelete(){
+    public void testDelete() {
         pruningDataTreeModification.delete(CarsModel.BASE_PATH);
 
         pruningDataTreeModification.delete(CarsModel.BASE_PATH);
 
-        verify(delegate).delete(CarsModel.BASE_PATH);
+        verify(mockModification, times(1)).delete(CarsModel.BASE_PATH);
     }
 
     @Test
     }
 
     @Test
-    public void testDeleteOnException(){
+    public void testDeleteOnException() {
         YangInstanceIdentifier path = CarsModel.BASE_PATH;
         YangInstanceIdentifier path = CarsModel.BASE_PATH;
-        doThrow(SchemaValidationFailedException.class).when(delegate).delete(path);
+        doThrow(SchemaValidationFailedException.class).when(mockModification).delete(path);
 
         pruningDataTreeModification.delete(path);
 
 
         pruningDataTreeModification.delete(path);
 
-        verify(delegate, times(1)).delete(path);
+        verify(mockModification, times(1)).delete(path);
     }
 
 
     @Test
     }
 
 
     @Test
-    public void testMerge(){
+    public void testMerge() {
         NormalizedNode<?, ?> normalizedNode = CarsModel.create();
         YangInstanceIdentifier path = CarsModel.BASE_PATH;
         pruningDataTreeModification.merge(path, normalizedNode);
 
         NormalizedNode<?, ?> normalizedNode = CarsModel.create();
         YangInstanceIdentifier path = CarsModel.BASE_PATH;
         pruningDataTreeModification.merge(path, normalizedNode);
 
-        verify(delegate, times(1)).merge(path, normalizedNode);
+        verify(mockModification, times(1)).merge(path, normalizedNode);
     }
 
     @Test
     }
 
     @Test
-    public void testMergeOnException(){
-        NormalizedNode<?, ?> normalizedNode = CarsModel.create();
-        YangInstanceIdentifier path = CarsModel.BASE_PATH;
+    public void testMergeWithInvalidNamespace() throws DataValidationFailedException {
+        NormalizedNode<?, ?> normalizedNode = PeopleModel.emptyContainer();
+        YangInstanceIdentifier path = PeopleModel.BASE_PATH;
+
+        pruningDataTreeModification.merge(path, normalizedNode);
 
 
-        doThrow(SchemaValidationFailedException.class).when(delegate).merge(path, normalizedNode);
-        doReturn(true).when(validNamespaces).contains(any(YangInstanceIdentifier.PathArgument.class));
+        verify(mockModification, times(1)).merge(path, normalizedNode);
+
+        DataTreeCandidate candidate = getCandidate();
+        assertEquals("getModificationType", ModificationType.UNMODIFIED, candidate.getRootNode().getModificationType());
+    }
+
+    @Test
+    public void testMergeWithInvalidChildNodeNames() throws DataValidationFailedException {
+        ContainerNode augContainer = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(AUG_CONTAINER)).withChild(
+                        ImmutableNodes.containerNode(AUG_INNER_CONTAINER)).build();
+
+        DataContainerChild<?, ?> outerNode = outerNode(outerNodeEntry(1, innerNode("one", "two")));
+        ContainerNode normalizedNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode)
+                .withChild(augContainer).withChild(ImmutableNodes.leafNode(AUG_QNAME, "aug")).build();
+
+        YangInstanceIdentifier path = TestModel.TEST_PATH;
+
+        pruningDataTreeModification.merge(path, normalizedNode);
+
+        dataTree.commit(getCandidate());
+
+        ContainerNode prunedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode).build();
+
+        Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(path);
+        assertTrue("After pruning present", actual.isPresent());
+        assertEquals("After pruning", prunedNode, actual.get());
+    }
+
+    @Test
+    public void testMergeWithValidNamespaceAndInvalidNodeName() throws DataValidationFailedException {
+        NormalizedNode<?, ?> normalizedNode = ImmutableNodes.containerNode(INVALID_TEST_QNAME);
+        YangInstanceIdentifier path = INVALID_TEST_PATH;
 
         pruningDataTreeModification.merge(path, normalizedNode);
 
 
         pruningDataTreeModification.merge(path, normalizedNode);
 
-        verify(delegate, times(1)).merge(path, normalizedNode);
-        verify(delegate, times(1)).merge(path, prunedNormalizedNode);
+        verify(mockModification, times(1)).merge(path, normalizedNode);
+
+        DataTreeCandidate candidate = getCandidate();
+        assertEquals("getModificationType", ModificationType.UNMODIFIED, candidate.getRootNode().getModificationType());
     }
 
     @Test
     }
 
     @Test
-    public void testWrite(){
+    public void testWrite() {
         NormalizedNode<?, ?> normalizedNode = CarsModel.create();
         YangInstanceIdentifier path = CarsModel.BASE_PATH;
         pruningDataTreeModification.write(path, normalizedNode);
 
         NormalizedNode<?, ?> normalizedNode = CarsModel.create();
         YangInstanceIdentifier path = CarsModel.BASE_PATH;
         pruningDataTreeModification.write(path, normalizedNode);
 
-        verify(delegate, times(1)).write(path, normalizedNode);
+        verify(mockModification, times(1)).write(path, normalizedNode);
     }
 
     @Test
     }
 
     @Test
-    public void testWriteOnException(){
-        NormalizedNode<?, ?> normalizedNode = CarsModel.create();
-        YangInstanceIdentifier path = CarsModel.BASE_PATH;
+    public void testWriteRootNode() throws Exception {
+        final DataTree localDataTree = new InMemoryDataTreeFactory().create(
+            DataTreeConfiguration.DEFAULT_CONFIGURATION, SCHEMA_CONTEXT);
+
+        DataTreeModification mod = localDataTree.takeSnapshot().newModification();
+        mod.write(CarsModel.BASE_PATH, CarsModel.create());
+        mod.ready();
+        localDataTree.validate(mod);
+        localDataTree.commit(localDataTree.prepare(mod));
+
+        NormalizedNode<?, ?> normalizedNode = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY).get();
+        pruningDataTreeModification.write(YangInstanceIdentifier.EMPTY, normalizedNode);
+        dataTree.commit(getCandidate());
+
+        Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY);
+        assertTrue("Root present", actual.isPresent());
+        assertEquals("Root node", normalizedNode, actual.get());
+    }
+
+    @Test
+    public void testWriteRootNodeWithInvalidChild() throws Exception {
+        final Shard mockShard = Mockito.mock(Shard.class);
+
+        ShardDataTree shardDataTree = new ShardDataTree(mockShard, SCHEMA_CONTEXT, TreeType.CONFIGURATION);
+        NormalizedNode<?, ?> root = shardDataTree.readNode(YangInstanceIdentifier.EMPTY).get();
+
+        NormalizedNode<?, ?> normalizedNode = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(root.getNodeType())).withChild(
+                        ImmutableNodes.containerNode(AUG_CONTAINER)).build();
+        pruningDataTreeModification.write(YangInstanceIdentifier.EMPTY, normalizedNode);
+        dataTree.commit(getCandidate());
 
 
-        doThrow(SchemaValidationFailedException.class).when(delegate).write(path, normalizedNode);
-        doReturn(true).when(validNamespaces).contains(any(YangInstanceIdentifier.PathArgument.class));
+        Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(YangInstanceIdentifier.EMPTY);
+        assertEquals("Root present", true, actual.isPresent());
+        assertEquals("Root node", root, actual.get());
+
+    }
+
+    @Test
+    public void testWriteWithInvalidNamespace() throws DataValidationFailedException {
+        NormalizedNode<?, ?> normalizedNode = PeopleModel.emptyContainer();
+        YangInstanceIdentifier path = PeopleModel.BASE_PATH;
 
         pruningDataTreeModification.write(path, normalizedNode);
 
 
         pruningDataTreeModification.write(path, normalizedNode);
 
-        verify(delegate, times(1)).write(path, normalizedNode);
-        verify(delegate, times(1)).write(path, prunedNormalizedNode);
+        verify(mockModification, times(1)).write(path, normalizedNode);
+
+        DataTreeCandidate candidate = getCandidate();
+        assertEquals("getModificationType", ModificationType.UNMODIFIED, candidate.getRootNode().getModificationType());
     }
 
     @Test
     }
 
     @Test
-    public void testReady(){
+    public void testWriteWithInvalidChildNodeNames() throws DataValidationFailedException {
+        ContainerNode augContainer = ImmutableContainerNodeBuilder.create().withNodeIdentifier(
+                new YangInstanceIdentifier.NodeIdentifier(AUG_CONTAINER)).withChild(
+                        ImmutableNodes.containerNode(AUG_INNER_CONTAINER)).build();
+
+        DataContainerChild<?, ?> outerNode = outerNode(outerNodeEntry(1, innerNode("one", "two")));
+        ContainerNode normalizedNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode)
+                .withChild(augContainer).withChild(ImmutableNodes.leafNode(AUG_QNAME, "aug"))
+                .withChild(ImmutableNodes.leafNode(NAME_QNAME, "name")).build();
+
+        YangInstanceIdentifier path = TestModel.TEST_PATH;
+
+        pruningDataTreeModification.write(path, normalizedNode);
+
+        dataTree.commit(getCandidate());
+
+        ContainerNode prunedNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TEST_QNAME)).withChild(outerNode)
+                .withChild(ImmutableNodes.leafNode(NAME_QNAME, "name")).build();
+
+        Optional<NormalizedNode<?, ?>> actual = dataTree.takeSnapshot().readNode(path);
+        assertTrue("After pruning present", actual.isPresent());
+        assertEquals("After pruning", prunedNode, actual.get());
+    }
+
+    @Test
+    public void testReady() {
         pruningDataTreeModification.ready();
 
         pruningDataTreeModification.ready();
 
-        verify(delegate).ready();
+        verify(mockModification).ready();
     }
 
     @Test
     }
 
     @Test
-    public void testApplyToCursor(){
+    public void testApplyToCursor() {
         DataTreeModificationCursor dataTreeModificationCursor = mock(DataTreeModificationCursor.class);
         pruningDataTreeModification.applyToCursor(dataTreeModificationCursor);
 
         DataTreeModificationCursor dataTreeModificationCursor = mock(DataTreeModificationCursor.class);
         pruningDataTreeModification.applyToCursor(dataTreeModificationCursor);
 
-        verify(delegate).applyToCursor(dataTreeModificationCursor);
+        verify(mockModification).applyToCursor(dataTreeModificationCursor);
     }
 
     @Test
     }
 
     @Test
-    public void testReadNode(){
+    public void testReadNode() {
         pruningDataTreeModification.readNode(CarsModel.BASE_PATH);
 
         pruningDataTreeModification.readNode(CarsModel.BASE_PATH);
 
-        verify(delegate).readNode(CarsModel.BASE_PATH);
+        verify(mockModification).readNode(CarsModel.BASE_PATH);
     }
 
     @Test
     }
 
     @Test
-    public void testNewModification(){
+    public void testNewModification() {
+        realModification.ready();
         DataTreeModification dataTreeModification = pruningDataTreeModification.newModification();
 
         DataTreeModification dataTreeModification = pruningDataTreeModification.newModification();
 
-        assertTrue("new modification not of type PruningDataTreeModification", dataTreeModification instanceof PruningDataTreeModification);
+        assertTrue("new modification not of type PruningDataTreeModification",
+                dataTreeModification instanceof PruningDataTreeModification);
+    }
+
+    private DataTreeCandidate getCandidate() throws DataValidationFailedException {
+        pruningDataTreeModification.ready();
+        DataTreeModification mod = pruningDataTreeModification.delegate();
+        mod = mod == proxyModification ? realModification : mod;
+        dataTree.validate(mod);
+        return dataTree.prepare(mod);
     }
     }
-}
\ No newline at end of file
+}