Improve integration tests for SubtreeWriter 18/10118/2
authorMarek Gradzki <mgradzki@cisco.com>
Tue, 16 Jan 2018 12:59:41 +0000 (13:59 +0100)
committerMarek Gradzki <mgradzki@cisco.com>
Tue, 16 Jan 2018 13:50:33 +0000 (13:50 +0000)
Change-Id: I20209b800eaa892e0fb742066003e956d00bbb22
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/AbstractInfraTest.java
infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/HoneycombWriteInfraTest.java
infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/SubtreeWriteTest.java [new file with mode: 0644]
infra/it/test-model/src/main/java/io/fd/honeycomb/subtree/test/model/Ids.java [new file with mode: 0644]
infra/it/test-model/src/main/yang/hc-subtree-test.yang [new file with mode: 0644]

index 3e25733..ebe9862 100644 (file)
@@ -71,7 +71,8 @@ abstract class AbstractInfraTest {
         final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
         moduleInfoBackedContext.addModuleInfos(Arrays.asList(
             org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.test.rev150105.$YangModuleInfoImpl.getInstance(),
-            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.$YangModuleInfoImpl.getInstance()
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.aug.test.rev161222.$YangModuleInfoImpl.getInstance(),
+            org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.$YangModuleInfoImpl.getInstance()
 
         ));
         return moduleInfoBackedContext;
index 54b93c7..6d8099c 100644 (file)
 
 package io.fd.honeycomb.data.impl;
 
-import static org.junit.Assert.fail;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
@@ -522,53 +520,4 @@ public class HoneycombWriteInfraTest extends AbstractInfraTest {
         // No modification
         verifyNoMoreInteractions(simpleContainerWriter);
     }
-
-    @Test
-    public void testSubtreeWriter() throws Exception {
-        writerRegistry = new FlatWriterRegistryBuilder(new YangDAG())
-                // Handles also container from grouping
-                .subtreeAdd(Sets.newHashSet(Ids.CONTAINER_FROM_GROUPING_ID), containerWithChoiceWriter)
-                .build();
-
-        final ModifiableDataTreeDelegator modifiableDataTreeDelegator =
-                new ModifiableDataTreeDelegator(serializer, dataTree, schemaContext, writerRegistry, contextBroker);
-
-        final ContainerWithChoice containerWithChoice =
-                new ContainerWithChoiceBuilder().setContainerFromGrouping(getContainerFromGrouping()).build();
-
-        // Test write subtree node
-        DataModification dataModification = modifiableDataTreeDelegator.newModification();
-        writeContainerFromGrouping(dataModification);
-        dataModification.commit();
-
-        verify(containerWithChoiceWriter, atLeastOnce()).getManagedDataObjectType();
-        verify(containerWithChoiceWriter)
-                .processModification(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(null), eq(containerWithChoice), any(WriteContext.class));
-        verifyNoMoreInteractions(containerWithChoiceWriter);
-
-        // Test delete sub-node
-        dataModification = modifiableDataTreeDelegator.newModification();
-        final ContainerWithChoice containerWithChoiceEmpty = new ContainerWithChoiceBuilder().build();
-        deleteContainerFromGrouping(dataModification);
-        dataModification.commit();
-
-        verify(containerWithChoiceWriter, atLeastOnce()).getManagedDataObjectType();
-        verify(containerWithChoiceWriter)
-                .processModification(eq(Ids.CONTAINER_WITH_CHOICE_ID), eq(containerWithChoice), eq(containerWithChoiceEmpty), any(WriteContext.class));
-        verifyNoMoreInteractions(containerWithChoiceWriter);
-
-        // Test write with subtree node that's not handled by subtree writer
-        dataModification = modifiableDataTreeDelegator.newModification();
-        writeContainerWithChoice(dataModification);
-        try {
-            dataModification.commit();
-            fail("Missing writer for C3 should occur");
-        } catch (IllegalArgumentException e) {
-            return;
-        }
-    }
-
-    private void deleteContainerFromGrouping(final DataModification dataModification) {
-        dataModification.delete(serializer.toYangInstanceIdentifier(Ids.CONTAINER_FROM_GROUPING_ID));
-    }
 }
\ No newline at end of file
diff --git a/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/SubtreeWriteTest.java b/infra/it/it-test/src/test/java/io/fd/honeycomb/data/impl/SubtreeWriteTest.java
new file mode 100644 (file)
index 0000000..f461747
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.data.impl;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.data.DataModification;
+import io.fd.honeycomb.subtree.test.model.Ids;
+import io.fd.honeycomb.translate.impl.write.registry.FlatWriterRegistryBuilder;
+import io.fd.honeycomb.translate.util.YangDAG;
+import io.fd.honeycomb.translate.write.WriteContext;
+import io.fd.honeycomb.translate.write.Writer;
+import io.fd.honeycomb.translate.write.registry.WriterRegistry;
+import java.util.Map;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.C1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.C1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C3Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C4;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C4Builder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+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.tree.InMemoryDataTreeFactory;
+
+/**
+ * Testing honeycomb writes from data tree up to mocked writers.
+ */
+public final class SubtreeWriteTest extends AbstractInfraTest {
+
+    private TipProducingDataTree dataTree;
+
+    @Mock
+    private Writer<C1> c1Writer;
+
+    @Override
+    void postSetup() {
+        dataTree = InMemoryDataTreeFactory.getInstance().create(TreeType.CONFIGURATION);
+        dataTree.setSchemaContext(schemaContext);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testMissingWriter() throws Exception {
+        when(c1Writer.getManagedDataObjectType()).thenReturn(Ids.C1_ID);
+
+        final WriterRegistry writerRegistry = new FlatWriterRegistryBuilder(new YangDAG())
+            .subtreeAdd(Sets.newHashSet(Ids.C2_ID, Ids.C3_ID), c1Writer)
+            .build();
+
+        // Prepare modification for C4
+        final ModifiableDataTreeDelegator modifiableDataTreeDelegator =
+            new ModifiableDataTreeDelegator(serializer, dataTree, schemaContext, writerRegistry, contextBroker);
+        final C4 c4 = new C4Builder().setLeaf4(4).build();
+        final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> c4NormalizedNode =
+            serializer.toNormalizedNode(Ids.C4_ID, c4);
+        final DataModification dataModification = modifiableDataTreeDelegator.newModification();
+        dataModification.write(c4NormalizedNode.getKey(), c4NormalizedNode.getValue());
+
+        // Commit modification and fail with missing writer for C4
+        dataModification.commit();
+    }
+
+    @Test
+    public void testWrite() throws Exception {
+        when(c1Writer.getManagedDataObjectType()).thenReturn(Ids.C1_ID);
+
+        final WriterRegistry writerRegistry = new FlatWriterRegistryBuilder(new YangDAG())
+            .subtreeAdd(Sets.newHashSet(Ids.C2_ID, Ids.C3_ID), c1Writer)
+            .build();
+
+        // Prepare modification for C1 and C2 containers
+        final ModifiableDataTreeDelegator modifiableDataTreeDelegator =
+            new ModifiableDataTreeDelegator(serializer, dataTree, schemaContext, writerRegistry, contextBroker);
+        final C2 c2 = new C2Builder().setLeaf2(2).build();
+        final C3 c3 = new C3Builder().setLeaf3(3).build();
+        final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> c2NormalizedNode =
+            serializer.toNormalizedNode(Ids.C2_ID, c2);
+        final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> c3NormalizedNode =
+            serializer.toNormalizedNode(Ids.C3_ID, c3);
+
+        // Create data
+        final DataModification dataModification = modifiableDataTreeDelegator.newModification();
+        dataModification.write(c2NormalizedNode.getKey(), c2NormalizedNode.getValue());
+        dataModification.write(c3NormalizedNode.getKey(), c3NormalizedNode.getValue());
+        dataModification.commit();
+
+        // Check if updates for two child containers are wrapped into single update
+        verify(c1Writer).processModification(any(), any(), any(), any());
+
+        // Verify that writer received create modification for C1 with C2 and C3 included
+        final C1 expectedC1 = new C1Builder().setC2(c2).setC3(c3).build();
+        verify(c1Writer).processModification(eq(Ids.C1_ID), eq(null), eq(expectedC1), any(WriteContext.class));
+    }
+
+    @Test
+    public void testDelete() throws Exception {
+        when(c1Writer.getManagedDataObjectType()).thenReturn(Ids.C1_ID);
+
+        final WriterRegistry writerRegistry = new FlatWriterRegistryBuilder(new YangDAG())
+            .subtreeAdd(Sets.newHashSet(Ids.C2_ID, Ids.C3_ID), c1Writer)
+            .build();
+
+        // Prepare C1 with leaf1 and C1, C2 containers
+        final ModifiableDataTreeDelegator modifiableDataTreeDelegator =
+            new ModifiableDataTreeDelegator(serializer, dataTree, schemaContext, writerRegistry, contextBroker);
+        final C2 c2 = new C2Builder().setLeaf2(2).build();
+        final C3 c3 = new C3Builder().setLeaf3(3).build();
+        final C1 c1 = new C1Builder().setC2(c2).setC3(c3).setLeaf1("some-value").build();
+        final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> c1NormalizedNode =
+            serializer.toNormalizedNode(Ids.C1_ID, c1);
+
+        // Create data
+        DataModification dataModification = modifiableDataTreeDelegator.newModification();
+        dataModification.write(c1NormalizedNode.getKey(), c1NormalizedNode.getValue());
+        dataModification.commit();
+        verify(c1Writer).processModification(eq(Ids.C1_ID), eq(null), eq(c1), any(WriteContext.class));
+
+        // Now delete C1 and C2
+        dataModification = modifiableDataTreeDelegator.newModification();
+        dataModification.delete(serializer.toYangInstanceIdentifier(Ids.C2_ID));
+        dataModification.delete(serializer.toYangInstanceIdentifier(Ids.C3_ID));
+        dataModification.commit();
+
+        // Check that in total, there were 2 invocations of processModification
+        verify(c1Writer, times(2)).processModification(any(), any(), any(), any());
+
+        // First create for C1
+        final InOrder inOrder = Mockito.inOrder(c1Writer);
+        inOrder.verify(c1Writer).processModification(eq(Ids.C1_ID), eq(null), eq(c1), any(WriteContext.class));
+
+        // Then delete for C1 and C2, but wrapped in C1 update
+        final C1 c1WithoutC2AndC3 = new C1Builder().setLeaf1("some-value").build();
+        inOrder.verify(c1Writer)
+            .processModification(eq(Ids.C1_ID), eq(c1), eq(c1WithoutC2AndC3), any(WriteContext.class));
+    }
+}
\ No newline at end of file
diff --git a/infra/it/test-model/src/main/java/io/fd/honeycomb/subtree/test/model/Ids.java b/infra/it/test-model/src/main/java/io/fd/honeycomb/subtree/test/model/Ids.java
new file mode 100644 (file)
index 0000000..52e8384
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.fd.honeycomb.subtree.test.model;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.C1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.hc.subtree.test.rev180116.c1.C4;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Instance identifiers referencing all complex nodes within honeycomb's subtree test model.
+ */
+public interface Ids {
+    InstanceIdentifier<C1> C1_ID = InstanceIdentifier.create(C1.class);
+    InstanceIdentifier<C2> C2_ID = C1_ID.child(C2.class);
+    InstanceIdentifier<C3> C3_ID = C1_ID.child(C3.class);
+    InstanceIdentifier<C4> C4_ID = C1_ID.child(C4.class);
+}
diff --git a/infra/it/test-model/src/main/yang/hc-subtree-test.yang b/infra/it/test-model/src/main/yang/hc-subtree-test.yang
new file mode 100644 (file)
index 0000000..09b3fc7
--- /dev/null
@@ -0,0 +1,30 @@
+module hc-subtree-test {
+  yang-version 1;
+  namespace "urn:opendaylight:params:xml:ns:yang:hc:subtree:test";
+  prefix "hc-subtree-test";
+
+  revision "2018-01-16" {
+    description "HC model for testing subtree writers.";
+  }
+
+  container c1 {
+    leaf leaf1 {
+      type string;
+    }
+    container c2 {
+      leaf leaf2 {
+        type int32;
+      }
+    }
+    container c3 {
+      leaf leaf3 {
+        type int32;
+      }
+    }
+    container c4 {
+      leaf leaf4 {
+        type int32;
+      }
+    }
+  }
+}