summaryrefslogtreecommitdiffstats
path: root/infra/translate-utils/src/test/java/io
diff options
context:
space:
mode:
authorMaros Marsalek <mmarsale@cisco.com>2016-07-27 11:05:51 +0200
committerMaros Marsalek <mmarsale@cisco.com>2016-07-29 16:32:07 +0200
commit0578156b721fa01c8c645b8f9625ecebdb6449e4 (patch)
tree49d36f24e5d984a8c9f151b1440de88619f8b7de /infra/translate-utils/src/test/java/io
parent007d4542388ca89be409ce1a4a4c7a36ddcb538f (diff)
HONEYCOMB-130: Separate v3po plugin from HC infra
Creating folders: - common/ - infra/ - v3po/ - vpp-common/ Change-Id: I2c39e1b17e39e7c0f0628f44aa5fe08563fa06e4 Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
Diffstat (limited to 'infra/translate-utils/src/test/java/io')
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/TransactionWriteContextTest.java131
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/DataObjects.java52
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/JsonUtilsTest.java109
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistryBuilderTest.java114
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReaderTest.java124
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/TypeHierarchyTest.java69
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryBuilderTest.java131
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryTest.java264
-rw-r--r--infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/SubtreeWriterTest.java84
9 files changed, 1078 insertions, 0 deletions
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/TransactionWriteContextTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/TransactionWriteContextTest.java
new file mode 100644
index 000000000..7c93e992a
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/impl/write/util/TransactionWriteContextTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.impl.write.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.Futures;
+import io.fd.honeycomb.v3po.translate.MappingContext;
+import io.fd.honeycomb.v3po.translate.ModificationCache;
+import io.fd.honeycomb.v3po.translate.util.DataObjects;
+import io.fd.honeycomb.v3po.translate.util.write.TransactionWriteContext;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public class TransactionWriteContextTest {
+
+ @Mock
+ private BindingNormalizedNodeSerializer serializer;
+ @Mock
+ private DOMDataReadOnlyTransaction beforeTx;
+ @Mock
+ private DOMDataReadOnlyTransaction afterTx;
+ @Mock
+ private Map.Entry entry;
+ @Mock
+ private MappingContext contextBroker;
+
+ private TransactionWriteContext transactionWriteContext;
+
+ @Before
+ public void setUp() {
+ initMocks(this);
+ transactionWriteContext = new TransactionWriteContext(serializer, beforeTx, afterTx, contextBroker);
+ }
+
+ @Test
+ public void testReadBeforeNoData() throws Exception {
+ when(beforeTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+ Futures.immediateCheckedFuture(Optional.absent()));
+
+ final InstanceIdentifier<DataObjects.DataObject1> instanceId =
+ InstanceIdentifier.create(DataObjects.DataObject1.class);
+
+ final Optional<DataObjects.DataObject1> dataObjects = transactionWriteContext.readBefore(instanceId);
+ assertNotNull(dataObjects);
+ assertFalse(dataObjects.isPresent());
+
+ verify(serializer).toYangInstanceIdentifier(instanceId);
+ verify(serializer, never()).fromNormalizedNode(any(YangInstanceIdentifier.class), any(NormalizedNode.class));
+ }
+
+ @Test
+ public void testReadBefore() throws Exception {
+ when(beforeTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+ Futures.immediateCheckedFuture(Optional.of(mock(NormalizedNode.class))));
+
+ final InstanceIdentifier<DataObjects.DataObject1> instanceId =
+ InstanceIdentifier.create(DataObjects.DataObject1.class);
+ final YangInstanceIdentifier yangId = YangInstanceIdentifier.builder().node(QName.create("n", "d")).build();
+ when(serializer.toYangInstanceIdentifier(any(InstanceIdentifier.class))).thenReturn(yangId);
+ when(serializer.fromNormalizedNode(eq(yangId), any(NormalizedNode.class))).thenReturn(entry);
+ when(entry.getValue()).thenReturn(mock(DataObjects.DataObject1.class));
+
+ final Optional<DataObjects.DataObject1> dataObjects = transactionWriteContext.readBefore(instanceId);
+ assertNotNull(dataObjects);
+ assertTrue(dataObjects.isPresent());
+
+ verify(serializer).toYangInstanceIdentifier(instanceId);
+ verify(serializer).fromNormalizedNode(eq(yangId), any(NormalizedNode.class));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testReadBeforeFailed() throws Exception {
+ when(beforeTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+ Futures.immediateFailedCheckedFuture(mock(ReadFailedException.class)));
+ transactionWriteContext.readBefore(mock(InstanceIdentifier.class));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testReadAfterFailed() throws Exception {
+ when(afterTx.read(eq(LogicalDatastoreType.CONFIGURATION), any(YangInstanceIdentifier.class))).thenReturn(
+ Futures.immediateFailedCheckedFuture(mock(ReadFailedException.class)));
+ transactionWriteContext.readAfter(mock(InstanceIdentifier.class));
+ }
+
+ @Test
+ public void testGetContext() throws Exception {
+ assertNotNull(transactionWriteContext.getModificationCache());
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ final ModificationCache context = transactionWriteContext.getModificationCache();
+ transactionWriteContext.close();
+ // TODO verify context was closed
+ }
+} \ No newline at end of file
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/DataObjects.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/DataObjects.java
new file mode 100644
index 000000000..d823465bd
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/DataObjects.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.util;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class DataObjects {
+ public interface DataObject1 extends DataObject {
+ InstanceIdentifier<DataObject1> IID = InstanceIdentifier.create(DataObject1.class);
+ }
+
+ public interface DataObject2 extends DataObject {
+ InstanceIdentifier<DataObject2> IID = InstanceIdentifier.create(DataObject2.class);
+ }
+
+ public interface DataObject3 extends DataObject {
+ InstanceIdentifier<DataObject3> IID = InstanceIdentifier.create(DataObject3.class);
+ interface DataObject31 extends DataObject, ChildOf<DataObject3> {
+ InstanceIdentifier<DataObject31> IID = DataObject3.IID.child(DataObject31.class);
+ }
+ }
+
+ public interface DataObject4 extends DataObject {
+ InstanceIdentifier<DataObject4> IID = InstanceIdentifier.create(DataObject4.class);
+ interface DataObject41 extends DataObject, ChildOf<DataObject4> {
+ InstanceIdentifier<DataObject41> IID = DataObject4.IID.child(DataObject41.class);
+ interface DataObject411 extends DataObject, ChildOf<DataObject41> {
+ InstanceIdentifier<DataObject411> IID = DataObject41.IID.child(DataObject411.class);
+ }
+ }
+
+ interface DataObject42 extends DataObject, ChildOf<DataObject4> {
+ InstanceIdentifier<DataObject42> IID = DataObject4.IID.child(DataObject42.class);
+ }
+ }
+}
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/JsonUtilsTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/JsonUtilsTest.java
new file mode 100644
index 000000000..bd48cb446
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/JsonUtilsTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.io.ByteStreams;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.MockitoAnnotations;
+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.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+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;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
+
+public class JsonUtilsTest {
+
+ public static final String NAMESPACE = "urn:opendaylight:params:xml:ns:yang:test:persistence";
+
+ private static final QName ROOT_QNAME = QName.create("urn:ietf:params:xml:ns:netconf:base:1.0", "data");
+ private static final QName TOP_CONTAINER_NAME = QName.create(NAMESPACE, "2015-01-05", "top-container");
+ private static final QName TOP_CONTAINER2_NAME = QName.create(NAMESPACE, "2015-01-05", "top-container2");
+ private static final QName STRING_LEAF_QNAME = QName.create(TOP_CONTAINER_NAME, "string");
+
+ private Path tmpPersistFile;
+ private EffectiveSchemaContext effectiveSchemaContext;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ tmpPersistFile = Files.createTempFile("testing-hc-persistence", "json");
+
+ final CrossSourceStatementReactor.BuildAction buildAction = YangInferencePipeline.RFC6020_REACTOR.newBuild();
+ buildAction.addSource(new YangStatementSourceImpl(getClass().getResourceAsStream("/test-persistence.yang")));
+ effectiveSchemaContext = buildAction.buildEffective();
+ }
+
+ @Test
+ public void testPersist() throws Exception {
+
+ NormalizedNode<?, ?> data = getData("testing");
+ JsonUtils.writeJsonRoot(data, effectiveSchemaContext, Files.newOutputStream(tmpPersistFile, StandardOpenOption.CREATE));
+ assertTrue(Files.exists(tmpPersistFile));
+
+ String persisted = new String(Files.readAllBytes(tmpPersistFile));
+ String expected =
+ new String(ByteStreams.toByteArray(getClass().getResourceAsStream("/expected-persisted-output.txt")));
+
+ assertEquals(expected, persisted);
+
+ data = getData("testing2");
+ JsonUtils.writeJsonRoot(data, effectiveSchemaContext, Files.newOutputStream(tmpPersistFile, StandardOpenOption.CREATE));
+ persisted = new String(Files.readAllBytes(tmpPersistFile));
+ assertEquals(expected.replace("testing", "testing2"), persisted);
+
+ // File has to stay even after close
+ assertTrue(Files.exists(tmpPersistFile));
+ }
+
+ @Test
+ public void testRestore() throws Exception {
+ final ContainerNode normalizedNodeOptional = JsonUtils
+ .readJsonRoot(effectiveSchemaContext, getClass().getResourceAsStream("/expected-persisted-output.txt"));
+ assertEquals(getData("testing"), normalizedNodeOptional);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRestoreInvalidFile() throws Exception {
+ JsonUtils.readJsonRoot(effectiveSchemaContext, getClass().getResourceAsStream("/test-persistence.yang"));
+ }
+
+ private ContainerNode getData(final String stringValue) {
+ return Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(ROOT_QNAME))
+ .withChild(Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER_NAME))
+ .withChild(ImmutableNodes.leafNode(STRING_LEAF_QNAME, stringValue))
+ .build())
+ .withChild(Builders.containerBuilder()
+ .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_CONTAINER2_NAME))
+ .withChild(ImmutableNodes.leafNode(STRING_LEAF_QNAME, stringValue))
+ .build())
+ .build();
+ }
+} \ No newline at end of file
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistryBuilderTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistryBuilderTest.java
new file mode 100644
index 000000000..e57dcee43
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/CompositeReaderRegistryBuilderTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.util.read.registry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.v3po.translate.read.Reader;
+import io.fd.honeycomb.v3po.translate.read.registry.ReaderRegistry;
+import io.fd.honeycomb.v3po.translate.util.DataObjects;
+import java.util.List;
+import java.util.Map;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class CompositeReaderRegistryBuilderTest {
+
+ private Reader<DataObjects.DataObject1, Builder<DataObjects.DataObject1>> reader1 =
+ mock(DataObjects.DataObject1.class);
+ private Reader<DataObjects.DataObject2, Builder<DataObjects.DataObject2>> reader2 =
+ mock(DataObjects.DataObject2.class);
+ private Reader<DataObjects.DataObject3, Builder<DataObjects.DataObject3>> reader3 =
+ mock(DataObjects.DataObject3.class);
+ private Reader<DataObjects.DataObject3.DataObject31, Builder<DataObjects.DataObject3.DataObject31>> reader31 =
+ mock(DataObjects.DataObject3.DataObject31.class);
+
+ private Reader<DataObjects.DataObject4, Builder<DataObjects.DataObject4>> reader4 =
+ mock(DataObjects.DataObject4.class);
+ private Reader<DataObjects.DataObject4.DataObject41, Builder<DataObjects.DataObject4.DataObject41>> reader41 =
+ mock(DataObjects.DataObject4.DataObject41.class);
+ private Reader<DataObjects.DataObject4.DataObject41.DataObject411, Builder<DataObjects.DataObject4.DataObject41.DataObject411>> reader411 =
+ mock(DataObjects.DataObject4.DataObject41.DataObject411.class);
+ private Reader<DataObjects.DataObject4.DataObject42, Builder<DataObjects.DataObject4.DataObject42>> reader42 =
+ mock(DataObjects.DataObject4.DataObject42.class);
+
+ @SuppressWarnings("unchecked")
+ private <D extends DataObject> Reader<D, Builder<D>> mock(final Class<D> dataObjectType) {
+ final Reader<D, Builder<D>> mock = Mockito.mock(Reader.class);
+ try {
+ when(mock.getManagedDataObjectType())
+ .thenReturn(((InstanceIdentifier<D>) dataObjectType.getDeclaredField("IID").get(null)));
+ } catch (IllegalAccessException | NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ }
+ return mock;
+ }
+
+ @Test
+ public void testCompositeStructure() throws Exception {
+ final CompositeReaderRegistryBuilder compositeReaderRegistryBuilder = new CompositeReaderRegistryBuilder();
+ /*
+ Composite reader structure ordered left from right
+
+ 1, 2, 3, 4
+ 31 42, 41
+ 411
+ */
+ compositeReaderRegistryBuilder.add(reader1);
+ compositeReaderRegistryBuilder.addAfter(reader2, reader1.getManagedDataObjectType());
+ compositeReaderRegistryBuilder.addAfter(reader3, reader2.getManagedDataObjectType());
+ compositeReaderRegistryBuilder.addAfter(reader31, reader1.getManagedDataObjectType());
+ compositeReaderRegistryBuilder.addAfter(reader4, reader3.getManagedDataObjectType());
+ compositeReaderRegistryBuilder.add(reader41);
+ compositeReaderRegistryBuilder.addBefore(reader42, reader41.getManagedDataObjectType());
+ compositeReaderRegistryBuilder.add(reader411);
+
+ final ReaderRegistry build = compositeReaderRegistryBuilder.build();
+
+ final Map<Class<? extends DataObject>, Reader<? extends DataObject, ? extends Builder<?>>> rootReaders =
+ ((CompositeReaderRegistry) build).getRootReaders();
+ final List<Class<? extends DataObject>> rootReaderOrder = Lists.newArrayList(rootReaders.keySet());
+
+ assertEquals(reader1.getManagedDataObjectType().getTargetType(), rootReaderOrder.get(0));
+ assertEquals(reader2.getManagedDataObjectType().getTargetType(), rootReaderOrder.get(1));
+ assertEquals(reader3.getManagedDataObjectType().getTargetType(), rootReaderOrder.get(2));
+ assertEquals(reader4.getManagedDataObjectType().getTargetType(), rootReaderOrder.get(3));
+
+ assertFalse(rootReaders.get(DataObjects.DataObject1.class) instanceof CompositeReader);
+ assertFalse(rootReaders.get(DataObjects.DataObject2.class) instanceof CompositeReader);
+ assertTrue(rootReaders.get(DataObjects.DataObject3.class) instanceof CompositeReader);
+ assertTrue(rootReaders.get(DataObjects.DataObject4.class) instanceof CompositeReader);
+
+ final ImmutableMap<Class<?>, Reader<? extends DataObject, ? extends Builder<?>>> childReaders =
+ ((CompositeReader<? extends DataObject, ? extends Builder<?>>) rootReaders
+ .get(DataObjects.DataObject4.class)).getChildReaders();
+ final List<Class<?>> orderedChildReaders = Lists.newArrayList(childReaders.keySet());
+
+ assertEquals(reader42.getManagedDataObjectType().getTargetType(), orderedChildReaders.get(0));
+ assertEquals(reader41.getManagedDataObjectType().getTargetType(), orderedChildReaders.get(1));
+ assertTrue(childReaders.get(DataObjects.DataObject4.DataObject41.class) instanceof CompositeReader);
+ assertFalse(childReaders.get(DataObjects.DataObject4.DataObject42.class) instanceof CompositeReader);
+ }
+} \ No newline at end of file
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReaderTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReaderTest.java
new file mode 100644
index 000000000..324d71daa
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/SubtreeReaderTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.util.read.registry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.v3po.translate.read.ReadContext;
+import io.fd.honeycomb.v3po.translate.read.Reader;
+import io.fd.honeycomb.v3po.translate.util.DataObjects;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubtreeReaderTest {
+
+ @Mock
+ private Reader<DataObjects.DataObject4, Builder<DataObjects.DataObject4>> delegate;
+ @Mock
+ private Reader<DataObject1, Builder<DataObject1>> delegateLocal;
+ @Mock
+ private ReadContext ctx;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ doReturn(DataObjects.DataObject4.IID).when(delegate).getManagedDataObjectType();
+ doReturn(DataObject1.IID).when(delegateLocal).getManagedDataObjectType();
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ final Reader<DataObjects.DataObject4, Builder<DataObjects.DataObject4>> subtreeR =
+ SubtreeReader.createForReader(Sets.newHashSet(DataObjects.DataObject4.DataObject41.IID), delegate);
+
+ subtreeR.getBuilder(DataObjects.DataObject4.IID);
+ verify(delegate).getBuilder(DataObjects.DataObject4.IID);
+
+ subtreeR.getManagedDataObjectType();
+ verify(delegate, atLeastOnce()).getManagedDataObjectType();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateInvalid() throws Exception {
+ SubtreeReader.createForReader(Sets.newHashSet(DataObjects.DataObject1.IID), delegate);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testReadOnlySubtreeCannotFilter() throws Exception {
+ final Reader<DataObjects.DataObject4, Builder<DataObjects.DataObject4>> subtreeR =
+ SubtreeReader.createForReader(Sets.newHashSet(DataObjects.DataObject4.DataObject41.IID), delegate);
+
+ doReturn(Optional.fromNullable(mock(DataObjects.DataObject4.class))).when(delegate).read(DataObjects.DataObject4.IID, ctx);
+ subtreeR.read(DataObjects.DataObject4.DataObject41.IID, ctx);
+ }
+
+ @Test
+ public void testReadOnlySubtreeNotPresent() throws Exception {
+ final Reader<DataObjects.DataObject4, Builder<DataObjects.DataObject4>> subtreeR =
+ SubtreeReader.createForReader(Sets.newHashSet(DataObjects.DataObject4.DataObject41.IID), delegate);
+
+ doReturn(Optional.absent()).when(delegate).read(DataObjects.DataObject4.IID, ctx);
+ assertFalse(subtreeR.read(DataObjects.DataObject4.DataObject41.IID, ctx).isPresent());
+ }
+
+ @Test
+ public void testReadOnlySubtreeChild() throws Exception {
+ final Reader<DataObject1, Builder<DataObject1>> subtreeR =
+ SubtreeReader.createForReader(Sets.newHashSet(DataObject1.DataObject11.IID), delegateLocal);
+
+ final DataObject1 mock = mock(DataObject1.class);
+ final DataObject1.DataObject11 mock11 = mock(DataObject1.DataObject11.class);
+ doReturn(mock11).when(mock).getDataObject11();
+ doReturn(Optional.fromNullable(mock)).when(delegateLocal).read(DataObject1.IID, ctx);
+ assertEquals(mock11, subtreeR.read(DataObject1.DataObject11.IID, ctx).get());
+ }
+
+ @Test
+ public void testReadEntireSubtree() throws Exception {
+ final Reader<DataObject1, Builder<DataObject1>> subtreeR =
+ SubtreeReader.createForReader(Sets.newHashSet(DataObject1.DataObject11.IID), delegateLocal);
+
+ final DataObject1 mock = mock(DataObject1.class);
+ final DataObject1.DataObject11 mock11 = mock(DataObject1.DataObject11.class);
+ doReturn(mock11).when(mock).getDataObject11();
+ doReturn(Optional.fromNullable(mock)).when(delegateLocal).read(DataObject1.IID, ctx);
+ assertEquals(mock, subtreeR.read(DataObject1.IID, ctx).get());
+ }
+
+ public abstract static class DataObject1 implements DataObject {
+ public static InstanceIdentifier<DataObject1> IID = InstanceIdentifier.create(DataObject1.class);
+
+ public abstract DataObject11 getDataObject11();
+
+ public abstract static class DataObject11 implements DataObject, ChildOf<DataObject1> {
+ public static InstanceIdentifier<DataObject11> IID = DataObject1.IID.child(DataObject11.class);
+ }
+ }
+}
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/TypeHierarchyTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/TypeHierarchyTest.java
new file mode 100644
index 000000000..7a664eef1
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/read/registry/TypeHierarchyTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.util.read.registry;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject1;
+import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject3;
+import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject4;
+import org.junit.Test;
+
+public class TypeHierarchyTest {
+
+ @Test
+ public void testHierarchy() throws Exception {
+ final TypeHierarchy typeHierarchy = TypeHierarchy.create(Sets.newHashSet(
+ DataObject4.DataObject41.DataObject411.IID,
+ DataObject4.DataObject41.IID,/* Included in previous already */
+ DataObject1.IID,
+ DataObject3.DataObject31.IID));
+
+ // Roots
+ assertThat(typeHierarchy.getRoots().size(), is(3));
+ assertThat(typeHierarchy.getRoots(), hasItems(DataObject1.IID, DataObject3.IID, DataObject4.IID));
+
+ // Leaves
+ assertThat(typeHierarchy.getDirectChildren(DataObject1.IID).size(), is(0));
+ assertThat(typeHierarchy.getDirectChildren(DataObject3.DataObject31.IID).size(), is(0));
+ assertThat(typeHierarchy.getDirectChildren(DataObject4.DataObject41.DataObject411.IID).size(), is(0));
+
+ // Intermediate leaves
+ assertThat(typeHierarchy.getDirectChildren(DataObject3.IID).size(), is(1));
+ assertThat(typeHierarchy.getDirectChildren(DataObject3.IID), hasItem(DataObject3.DataObject31.IID));
+ assertEquals(typeHierarchy.getDirectChildren(DataObject3.IID), typeHierarchy.getAllChildren(DataObject3.IID));
+
+ assertThat(typeHierarchy.getDirectChildren(DataObject4.DataObject41.IID).size(), is(1));
+ assertThat(typeHierarchy.getDirectChildren(DataObject4.DataObject41.IID), hasItem(
+ DataObject4.DataObject41.DataObject411.IID));
+ assertEquals(typeHierarchy.getDirectChildren(DataObject4.DataObject41.IID), typeHierarchy.getAllChildren(
+ DataObject4.DataObject41.IID));
+
+ assertThat(typeHierarchy.getDirectChildren(DataObject4.IID).size(), is(1));
+ assertThat(typeHierarchy.getDirectChildren(DataObject4.IID), hasItem(DataObject4.DataObject41.IID));
+ assertThat(typeHierarchy.getAllChildren(DataObject4.IID).size(), is(2));
+ assertTrue(typeHierarchy.getAllChildren(DataObject4.IID).contains(DataObject4.DataObject41.IID));
+ assertTrue(typeHierarchy.getAllChildren(DataObject4.IID).contains(DataObject4.DataObject41.DataObject411.IID));
+ }
+}
+
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryBuilderTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryBuilderTest.java
new file mode 100644
index 000000000..743d84cbf
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryBuilderTest.java
@@ -0,0 +1,131 @@
+package io.fd.honeycomb.v3po.translate.util.write.registry;
+
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.hasItems;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.v3po.translate.util.DataObjects;
+import io.fd.honeycomb.v3po.translate.write.Writer;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FlatWriterRegistryBuilderTest {
+
+
+ @Test
+ public void testRelationsBefore() throws Exception {
+ final FlatWriterRegistryBuilder flatWriterRegistryBuilder = new FlatWriterRegistryBuilder();
+ /*
+ 1 -> 2 -> 3
+ -> 4
+ */
+ flatWriterRegistryBuilder.add(mockWriter(DataObjects.DataObject3.class));
+ flatWriterRegistryBuilder.add(mockWriter(DataObjects.DataObject4.class));
+ flatWriterRegistryBuilder.addBefore(mockWriter(DataObjects.DataObject2.class),
+ Lists.newArrayList(DataObjects.DataObject3.IID, DataObjects.DataObject4.IID));
+ flatWriterRegistryBuilder.addBefore(mockWriter(DataObjects.DataObject1.class), DataObjects.DataObject2.IID);
+ final ImmutableMap<InstanceIdentifier<?>, Writer<?>> mappedWriters =
+ flatWriterRegistryBuilder.getMappedHandlers();
+
+ final ArrayList<InstanceIdentifier<?>> typesInList = Lists.newArrayList(mappedWriters.keySet());
+ assertEquals(DataObjects.DataObject1.IID, typesInList.get(0));
+ assertEquals(DataObjects.DataObject2.IID, typesInList.get(1));
+ assertThat(typesInList.get(2), anyOf(equalTo(DataObjects.DataObject3.IID), equalTo(DataObjects.DataObject4.IID)));
+ assertThat(typesInList.get(3), anyOf(equalTo(DataObjects.DataObject3.IID), equalTo(DataObjects.DataObject4.IID)));
+ }
+
+ @Test
+ public void testRelationsAfter() throws Exception {
+ final FlatWriterRegistryBuilder flatWriterRegistryBuilder = new FlatWriterRegistryBuilder();
+ /*
+ 1 -> 2 -> 3
+ -> 4
+ */
+ flatWriterRegistryBuilder.add(mockWriter(DataObjects.DataObject1.class));
+ flatWriterRegistryBuilder.addAfter(mockWriter(DataObjects.DataObject2.class), DataObjects.DataObject1.IID);
+ flatWriterRegistryBuilder.addAfter(mockWriter(DataObjects.DataObject3.class), DataObjects.DataObject2.IID);
+ flatWriterRegistryBuilder.addAfter(mockWriter(DataObjects.DataObject4.class), DataObjects.DataObject2.IID);
+ final ImmutableMap<InstanceIdentifier<?>, Writer<?>> mappedWriters =
+ flatWriterRegistryBuilder.getMappedHandlers();
+
+ final List<InstanceIdentifier<?>> typesInList = Lists.newArrayList(mappedWriters.keySet());
+ assertEquals(DataObjects.DataObject1.IID, typesInList.get(0));
+ assertEquals(DataObjects.DataObject2.IID, typesInList.get(1));
+ assertThat(typesInList.get(2), anyOf(equalTo(DataObjects.DataObject3.IID), equalTo(DataObjects.DataObject4.IID)));
+ assertThat(typesInList.get(3), anyOf(equalTo(DataObjects.DataObject3.IID), equalTo(DataObjects.DataObject4.IID)));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRelationsLoop() throws Exception {
+ final FlatWriterRegistryBuilder flatWriterRegistryBuilder = new FlatWriterRegistryBuilder();
+ /*
+ 1 -> 2 -> 1
+ */
+ flatWriterRegistryBuilder.add(mockWriter(DataObjects.DataObject1.class));
+ flatWriterRegistryBuilder.addAfter(mockWriter(DataObjects.DataObject2.class), DataObjects.DataObject1.IID);
+ flatWriterRegistryBuilder.addAfter(mockWriter(DataObjects.DataObject1.class), DataObjects.DataObject2.IID);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testAddWriterTwice() throws Exception {
+ final FlatWriterRegistryBuilder flatWriterRegistryBuilder = new FlatWriterRegistryBuilder();
+ flatWriterRegistryBuilder.add(mockWriter(DataObjects.DataObject1.class));
+ flatWriterRegistryBuilder.add(mockWriter(DataObjects.DataObject1.class));
+ }
+
+ @Test
+ public void testAddSubtreeWriter() throws Exception {
+ final FlatWriterRegistryBuilder flatWriterRegistryBuilder = new FlatWriterRegistryBuilder();
+ flatWriterRegistryBuilder.subtreeAdd(
+ Sets.newHashSet(DataObjects.DataObject4.DataObject41.IID,
+ DataObjects.DataObject4.DataObject41.IID),
+ mockWriter(DataObjects.DataObject4.class));
+ final ImmutableMap<InstanceIdentifier<?>, Writer<?>> mappedWriters =
+ flatWriterRegistryBuilder.getMappedHandlers();
+ final ArrayList<InstanceIdentifier<?>> typesInList = Lists.newArrayList(mappedWriters.keySet());
+
+ assertEquals(DataObjects.DataObject4.IID, typesInList.get(0));
+ assertEquals(1, typesInList.size());
+ }
+
+ @Test
+ public void testCreateSubtreeWriter() throws Exception {
+ final Writer<?> forWriter = SubtreeWriter.createForWriter(Sets.newHashSet(
+ DataObjects.DataObject4.DataObject41.IID,
+ DataObjects.DataObject4.DataObject41.DataObject411.IID,
+ DataObjects.DataObject4.DataObject42.IID),
+ mockWriter(DataObjects.DataObject4.class));
+ assertThat(forWriter, instanceOf(SubtreeWriter.class));
+ assertThat(((SubtreeWriter<?>) forWriter).getHandledChildTypes().size(), is(3));
+ assertThat(((SubtreeWriter<?>) forWriter).getHandledChildTypes(), hasItems(DataObjects.DataObject4.DataObject41.IID,
+ DataObjects.DataObject4.DataObject42.IID, DataObjects.DataObject4.DataObject41.DataObject411.IID));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateInvalidSubtreeWriter() throws Exception {
+ SubtreeWriter.createForWriter(Sets.newHashSet(
+ InstanceIdentifier.create(DataObjects.DataObject3.class).child(DataObjects.DataObject3.DataObject31.class)),
+ mockWriter(DataObjects.DataObject4.class));
+ }
+
+ @SuppressWarnings("unchecked")
+ private Writer<? extends DataObject> mockWriter(final Class<? extends DataObject> doClass)
+ throws NoSuchFieldException, IllegalAccessException {
+ final Writer mock = mock(Writer.class);
+ when(mock.getManagedDataObjectType()).thenReturn((InstanceIdentifier<?>) doClass.getDeclaredField("IID").get(null));
+ return mock;
+ }
+
+} \ No newline at end of file
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryTest.java
new file mode 100644
index 000000000..a72cb4fa7
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/FlatWriterRegistryTest.java
@@ -0,0 +1,264 @@
+package io.fd.honeycomb.v3po.translate.util.write.registry;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Multimap;
+import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject1;
+import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject2;
+import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject3;
+import io.fd.honeycomb.v3po.translate.write.DataObjectUpdate;
+import io.fd.honeycomb.v3po.translate.write.WriteContext;
+import io.fd.honeycomb.v3po.translate.write.Writer;
+import io.fd.honeycomb.v3po.translate.write.registry.WriterRegistry;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class FlatWriterRegistryTest {
+
+ @Mock
+ private Writer<DataObject1> writer1;
+ @Mock
+ private Writer<DataObject2> writer2;
+ @Mock
+ private Writer<DataObject3> writer3;
+ @Mock
+ private WriteContext ctx;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(writer1.getManagedDataObjectType()).thenReturn(DataObject1.IID);
+ when(writer2.getManagedDataObjectType()).thenReturn(DataObject2.IID);
+ when(writer3.getManagedDataObjectType()).thenReturn(DataObject3.IID);
+ }
+
+ @Test
+ public void testMultipleUpdatesForSingleWriter() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
+ final InstanceIdentifier<DataObject1> iid2 = InstanceIdentifier.create(DataObject1.class);
+ final DataObject1 dataObject = mock(DataObject1.class);
+ updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
+ updates.put(DataObject1.IID, DataObjectUpdate.create(iid2, dataObject, dataObject));
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+
+ verify(writer1).update(iid, dataObject, dataObject, ctx);
+ verify(writer1).update(iid2, dataObject, dataObject, ctx);
+ // Invoked when registry is being created
+ verifyNoMoreInteractions(writer1);
+ verifyZeroInteractions(writer2);
+ }
+
+ @Test
+ public void testMultipleUpdatesForMultipleWriters() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
+ final DataObject1 dataObject = mock(DataObject1.class);
+ updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
+ final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
+ final DataObject2 dataObject2 = mock(DataObject2.class);
+ updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+
+ final InOrder inOrder = inOrder(writer1, writer2);
+ inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
+ inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
+
+ verifyNoMoreInteractions(writer1);
+ verifyNoMoreInteractions(writer2);
+ }
+
+ @Test
+ public void testMultipleDeletesForMultipleWriters() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
+ final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
+ final DataObject1 dataObject = mock(DataObject1.class);
+ deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
+ final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
+ final DataObject2 dataObject2 = mock(DataObject2.class);
+ deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(ImmutableMultimap.of(), deletes), ctx);
+
+ final InOrder inOrder = inOrder(writer1, writer2);
+ // Reversed order of invocation, first writer2 and then writer1
+ inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
+ inOrder.verify(writer1).update(iid, dataObject, null, ctx);
+
+ verifyNoMoreInteractions(writer1);
+ verifyNoMoreInteractions(writer2);
+ }
+
+ @Test
+ public void testMultipleUpdatesAndDeletesForMultipleWriters() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
+ final DataObject1 dataObject = mock(DataObject1.class);
+ // Writer 1 delete
+ deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
+ // Writer 1 update
+ updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
+ final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
+ final DataObject2 dataObject2 = mock(DataObject2.class);
+ // Writer 2 delete
+ deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
+ // Writer 2 update
+ updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, deletes), ctx);
+
+ final InOrder inOrder = inOrder(writer1, writer2);
+ // Reversed order of invocation, first writer2 and then writer1 for deletes
+ inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
+ inOrder.verify(writer1).update(iid, dataObject, null, ctx);
+ // Then also updates are processed
+ inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
+ inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
+
+ verifyNoMoreInteractions(writer1);
+ verifyNoMoreInteractions(writer2);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMultipleUpdatesOneMissing() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ addUpdate(updates, DataObject1.class);
+ addUpdate(updates, DataObject2.class);
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ }
+
+ @Test
+ public void testMultipleUpdatesOneFailing() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
+
+ // Writer1 always fails
+ doThrow(new RuntimeException()).when(writer1)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ addUpdate(updates, DataObject1.class);
+ addUpdate(updates, DataObject2.class);
+
+ try {
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ fail("Bulk update should have failed on writer1");
+ } catch (WriterRegistry.BulkUpdateException e) {
+ assertThat(e.getFailedIds().size(), is(2));
+ assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject2.class)));
+ assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject1.class)));
+ }
+ }
+
+ @Test
+ public void testMultipleUpdatesOneFailingThenRevertWithSuccess() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(
+ ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
+
+ // Writer1 always fails
+ doThrow(new RuntimeException()).when(writer3)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ addUpdate(updates, DataObject1.class);
+ addUpdate(updates, DataObject3.class);
+ final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
+ final DataObject2 before2 = mock(DataObject2.class);
+ final DataObject2 after2 = mock(DataObject2.class);
+ updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, before2, after2));
+
+ try {
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ fail("Bulk update should have failed on writer1");
+ } catch (WriterRegistry.BulkUpdateException e) {
+ assertThat(e.getFailedIds().size(), is(1));
+
+ final InOrder inOrder = inOrder(writer1, writer2, writer3);
+ inOrder.verify(writer1)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ inOrder.verify(writer2)
+ .update(iid2, before2, after2, ctx);
+ inOrder.verify(writer3)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+
+ e.revertChanges();
+ // Revert changes. Successful updates are iterated in reverse
+ inOrder.verify(writer2)
+ .update(iid2, after2, before2, ctx);
+ inOrder.verify(writer1)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ verifyNoMoreInteractions(writer3);
+ }
+ }
+
+ @Test
+ public void testMultipleUpdatesOneFailingThenRevertWithFail() throws Exception {
+ final FlatWriterRegistry flatWriterRegistry =
+ new FlatWriterRegistry(
+ ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
+
+ // Writer1 always fails
+ doThrow(new RuntimeException()).when(writer3)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+
+ final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
+ addUpdate(updates, DataObject1.class);
+ addUpdate(updates, DataObject2.class);
+ addUpdate(updates, DataObject3.class);
+
+ try {
+ flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
+ fail("Bulk update should have failed on writer1");
+ } catch (WriterRegistry.BulkUpdateException e) {
+ // Writer1 always fails from now
+ doThrow(new RuntimeException()).when(writer1)
+ .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
+ try {
+ e.revertChanges();
+ } catch (WriterRegistry.Reverter.RevertFailedException e1) {
+ assertThat(e1.getNotRevertedChanges().size(), is(1));
+ assertThat(e1.getNotRevertedChanges(), hasItem(InstanceIdentifier.create(DataObject1.class)));
+ }
+ }
+ }
+
+ private <D extends DataObject> void addUpdate(final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates,
+ final Class<D> type) throws Exception {
+ final InstanceIdentifier<D> iid = (InstanceIdentifier<D>) type.getDeclaredField("IID").get(null);
+ updates.put(iid, DataObjectUpdate.create(iid, mock(type), mock(type)));
+ }
+} \ No newline at end of file
diff --git a/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/SubtreeWriterTest.java b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/SubtreeWriterTest.java
new file mode 100644
index 000000000..627c69c92
--- /dev/null
+++ b/infra/translate-utils/src/test/java/io/fd/honeycomb/v3po/translate/util/write/registry/SubtreeWriterTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 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.v3po.translate.util.write.registry;
+
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.v3po.translate.util.DataObjects;
+import io.fd.honeycomb.v3po.translate.write.Writer;
+import java.util.Collections;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubtreeWriterTest {
+
+ @Mock
+ Writer<DataObjects.DataObject4> writer;
+ @Mock
+ Writer<DataObjects.DataObject4.DataObject41> writer11;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ when(writer.getManagedDataObjectType()).thenReturn(DataObjects.DataObject4.IID);
+ when(writer11.getManagedDataObjectType()).thenReturn(DataObjects.DataObject4.DataObject41.IID);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubtreeWriterCreationFail() throws Exception {
+ // The subtree node identified by IID.c(DataObject.class) is not a child of writer.getManagedDataObjectType
+ SubtreeWriter.createForWriter(Collections.singleton(InstanceIdentifier.create(DataObject.class)), writer);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSubtreeWriterCreationFailInvalidIid() throws Exception {
+ // The subtree node identified by IID.c(DataObject.class) is not a child of writer.getManagedDataObjectType
+ SubtreeWriter.createForWriter(Collections.singleton(DataObjects.DataObject4.IID), writer);
+ }
+
+ @Test
+ public void testSubtreeWriterCreation() throws Exception {
+ final SubtreeWriter<?> forWriter = (SubtreeWriter<?>) SubtreeWriter.createForWriter(Sets.newHashSet(
+ DataObjects.DataObject4.DataObject41.IID,
+ DataObjects.DataObject4.DataObject41.DataObject411.IID,
+ DataObjects.DataObject4.DataObject42.IID),
+ writer);
+
+ assertEquals(writer.getManagedDataObjectType(), forWriter.getManagedDataObjectType());
+ assertEquals(3, forWriter.getHandledChildTypes().size());
+ }
+
+ @Test
+ public void testSubtreeWriterHandledTypes() throws Exception {
+ final SubtreeWriter<?> forWriter = (SubtreeWriter<?>) SubtreeWriter.createForWriter(Sets.newHashSet(
+ DataObjects.DataObject4.DataObject41.DataObject411.IID),
+ writer);
+
+ assertEquals(writer.getManagedDataObjectType(), forWriter.getManagedDataObjectType());
+ assertEquals(1, forWriter.getHandledChildTypes().size());
+ assertThat(forWriter.getHandledChildTypes(), hasItem(DataObjects.DataObject4.DataObject41.DataObject411.IID));
+ }
+
+} \ No newline at end of file