HONEYCOMB-331: unify initialization handling 16/4616/1
authorMarek Gradzki <mgradzki@cisco.com>
Mon, 9 Jan 2017 07:23:45 +0000 (08:23 +0100)
committerMarek Gradzki <mgradzki@cisco.com>
Tue, 10 Jan 2017 07:41:32 +0000 (07:41 +0000)
Due to incorrect instance of check, InitSubtreeReader was never created
in CompositeReaderRegistryBuilder.getSubtreeHandler().

As a consequence, initializers registered by subtreeAdd*, were not invoked.

The patch:
- fixes mentioned check,
- makes readers implement InitReader instead of directly
  implementing Initializer
- includes missing unit tests for GenericReaders.

Change-Id: I93be59fafddb60dce00191958b5c8c62e7c2d289
Signed-off-by: Marek Gradzki <mgradzki@cisco.com>
12 files changed:
infra/translate-api/src/main/java/io/fd/honeycomb/translate/read/InitListReader.java
infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/GenericInitReader.java
infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/CompositeReader.java
infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/CompositeReaderRegistryBuilder.java
infra/translate-impl/src/main/java/io/fd/honeycomb/translate/impl/read/registry/InitSubtreeReader.java
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/AbstractListReaderTest.java [new file with mode: 0644]
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/AbstractReaderTest.java [new file with mode: 0644]
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericInitListReaderTest.java [new file with mode: 0644]
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericIntReaderTest.java [new file with mode: 0644]
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericListReaderTest.java
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericReaderTest.java
infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/registry/InitSubtreeReaderTest.java [new file with mode: 0644]

index a7d3ee2..f137aac 100644 (file)
@@ -27,5 +27,5 @@ import org.opendaylight.yangtools.yang.binding.Identifier;
  */
 @Beta
 public interface InitListReader<O extends DataObject & Identifiable<K>, K extends Identifier<O>, B extends Builder<O>>
-        extends ListReader<O, K, B>, Initializer<O> {
+        extends ListReader<O, K, B>, InitReader<O, B> {
 }
index 024e0a8..e55bc8a 100644 (file)
@@ -20,7 +20,7 @@ import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastor
 
 import com.google.common.base.Optional;
 import io.fd.honeycomb.translate.read.InitFailedException;
-import io.fd.honeycomb.translate.read.Initializer;
+import io.fd.honeycomb.translate.read.InitReader;
 import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.read.ReadFailedException;
 import io.fd.honeycomb.translate.spi.read.Initialized;
@@ -36,7 +36,7 @@ import org.slf4j.LoggerFactory;
 
 public final class GenericInitReader<O extends DataObject, B extends Builder<O>>
         extends GenericReader<O, B>
-        implements Initializer<O> {
+        implements InitReader<O, B> {
 
     private static final Logger LOG = LoggerFactory.getLogger(GenericInitReader.class);
 
index ec82b3f..2eca895 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 import io.fd.honeycomb.translate.read.InitFailedException;
 import io.fd.honeycomb.translate.read.InitListReader;
+import io.fd.honeycomb.translate.read.InitReader;
 import io.fd.honeycomb.translate.read.Initializer;
 import io.fd.honeycomb.translate.read.ListReader;
 import io.fd.honeycomb.translate.read.ReadContext;
@@ -47,7 +48,7 @@ import org.slf4j.LoggerFactory;
 
 class CompositeReader<D extends DataObject, B extends Builder<D>>
         extends AbstractGenericReader<D, B>
-        implements Initializer<D>, DelegatingReader<D, B> {
+        implements InitReader<D, B>, DelegatingReader<D, B> {
 
     private static final Logger LOG = LoggerFactory.getLogger(CompositeReader.class);
 
index 290c5d4..36ab909 100644 (file)
@@ -19,6 +19,7 @@ package io.fd.honeycomb.translate.impl.read.registry;
 import com.google.common.collect.ImmutableMap;
 import io.fd.honeycomb.translate.impl.read.GenericReader;
 import io.fd.honeycomb.translate.read.InitReader;
+import io.fd.honeycomb.translate.read.Initializer;
 import io.fd.honeycomb.translate.read.Reader;
 import io.fd.honeycomb.translate.read.registry.ModifiableReaderRegistryBuilder;
 import io.fd.honeycomb.translate.read.registry.ReaderRegistry;
@@ -46,8 +47,8 @@ public final class CompositeReaderRegistryBuilder
     @Override
     protected Reader<? extends DataObject, ? extends Builder<?>> getSubtreeHandler(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
                                                                                    @Nonnull final Reader<? extends DataObject, ? extends Builder<?>> reader) {
-        return reader instanceof InitReader
-                ? InitSubtreeReader.createForReader(handledChildren, reader)
+        return reader instanceof Initializer
+                ? InitSubtreeReader.createForReader(handledChildren, (InitReader<?, ?>)reader)
                 : SubtreeReader.createForReader(handledChildren, reader);
     }
 
index 809cdb2..e7cef81 100644 (file)
@@ -21,7 +21,6 @@ import io.fd.honeycomb.translate.read.InitListReader;
 import io.fd.honeycomb.translate.read.InitReader;
 import io.fd.honeycomb.translate.read.ListReader;
 import io.fd.honeycomb.translate.read.ReadContext;
-import io.fd.honeycomb.translate.read.Reader;
 import java.util.Set;
 import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -48,11 +47,11 @@ class InitSubtreeReader<O extends DataObject, B extends Builder<O>>
     /**
      * Wrap a Reader as an initializing subtree Reader.
      */
-    static <D extends DataObject, B extends Builder<D>> Reader<D, B> createForReader(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
-                                                                                     @Nonnull final Reader<D, B> reader) {
+    static <D extends DataObject, B extends Builder<D>> InitReader<D, B> createForReader(@Nonnull final Set<InstanceIdentifier<?>> handledChildren,
+                                                                                     @Nonnull final InitReader<D, B> reader) {
         return (reader instanceof ListReader)
                 ? new InitSubtreeListReader<>((InitListReader) reader, handledChildren)
-                : new InitSubtreeReader<>(((InitReader<D, B>) reader), handledChildren);
+                : new InitSubtreeReader<>(reader, handledChildren);
     }
 
     private static class InitSubtreeListReader<D extends DataObject & Identifiable<K>, B extends Builder<D>, K extends Identifier<D>>
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/AbstractListReaderTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/AbstractListReaderTest.java
new file mode 100644 (file)
index 0000000..5c08ce2
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2017 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.translate.impl.read;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.Lists;
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
+import java.util.List;
+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.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class AbstractListReaderTest {
+
+    protected static final InstanceIdentifier<TestingData>
+            DATA_OBJECT_ID = InstanceIdentifier.create(TestingData.class);
+
+    private final Class<? extends ListReaderCustomizer> customizerClass;
+
+    @Mock
+    protected Builder<TestingData> builder;
+    @Mock
+    protected TestingData data;
+    @Mock
+    protected ReadContext ctx;
+    private List<TestingData.TestingKey> keys = Lists.newArrayList(new TestingData.TestingKey(),
+            new TestingData.TestingKey());
+
+    private ListReaderCustomizer<TestingData, TestingData.TestingKey, Builder<TestingData>> customizer;
+    private GenericListReader<TestingData, TestingData.TestingKey, Builder<TestingData>> reader;
+
+    protected AbstractListReaderTest(final Class<? extends ListReaderCustomizer> customizerClass) {
+        this.customizerClass = customizerClass;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        customizer = mock(customizerClass);
+        when(customizer.getBuilder(any(InstanceIdentifier.class))).thenReturn(builder);
+        when(customizer.getAllIds(DATA_OBJECT_ID, ctx)).thenReturn(keys);
+        reader = initReader();
+        when(builder.build()).thenReturn(data);
+    }
+
+    protected abstract GenericListReader<TestingData,TestingData.TestingKey,Builder<TestingData>> initReader();
+
+    public GenericListReader<TestingData, TestingData.TestingKey, Builder<TestingData>> getReader() {
+        return reader;
+    }
+
+    protected ListReaderCustomizer<TestingData, TestingData.TestingKey, Builder<TestingData>> getCustomizer() {
+        return customizer;
+    }
+
+    @Test
+    public void testGetBuilder() throws Exception {
+        assertEquals(builder, reader.getBuilder(DATA_OBJECT_ID));
+        verify(customizer).getBuilder(DATA_OBJECT_ID);
+    }
+
+    @Test
+    public void testManagedType() throws Exception {
+        assertEquals(DATA_OBJECT_ID, reader.getManagedDataObjectType());
+    }
+
+    @Test
+    public void testMerge() throws Exception {
+        reader.merge(builder, data);
+        verify(customizer).merge(builder, data);
+    }
+
+    @Test
+    public void testAllIds() throws Exception {
+        assertEquals(keys, reader.getAllIds(DATA_OBJECT_ID, ctx));
+        verify(customizer).getAllIds(DATA_OBJECT_ID, ctx);
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        reader.read(DATA_OBJECT_ID, ctx);
+
+        verify(customizer).getBuilder(DATA_OBJECT_ID);
+        verify(customizer).readCurrentAttributes(DATA_OBJECT_ID, builder, ctx);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testReadList() throws Exception {
+        reader.readList(DATA_OBJECT_ID, ctx);
+
+        verify(customizer, times(2)).getBuilder(any(InstanceIdentifier.class));
+        verify(customizer, times(2))
+                .readCurrentAttributes(any(InstanceIdentifier.class), any(Builder.class), any(ReadContext.class));
+    }
+
+    static class TestingData implements DataObject, Identifiable<TestingData.TestingKey> {
+
+        @Override
+        public Class<? extends DataContainer> getImplementedInterface() {
+            return DataObject.class;
+        }
+
+        @Override
+        public TestingKey getKey() {
+            return new TestingKey();
+        }
+
+        static class TestingKey implements Identifier<TestingData> {}
+    }
+}
\ No newline at end of file
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/AbstractReaderTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/AbstractReaderTest.java
new file mode 100644 (file)
index 0000000..cac3217
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017 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.translate.impl.read;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.read.ReadContext;
+import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
+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.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public abstract class AbstractReaderTest {
+
+    protected static final InstanceIdentifier<DataObject>
+            DATA_OBJECT_ID = InstanceIdentifier.create(DataObject.class);
+    private final Class<? extends ReaderCustomizer> customizerClass;
+
+    @Mock
+    protected Builder<DataObject> builder;
+    @Mock
+    protected DataObject data;
+    @Mock
+    protected ReadContext ctx;
+
+    private ReaderCustomizer<DataObject, Builder<DataObject>> customizer;
+    private GenericReader<DataObject, Builder<DataObject>> reader;
+
+    protected AbstractReaderTest(final Class<? extends ReaderCustomizer> customizerClass) {
+        this.customizerClass = customizerClass;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Before
+    public final void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        customizer = mock(customizerClass);
+        when(customizer.getBuilder(DATA_OBJECT_ID)).thenReturn(builder);
+        reader = initReader();
+        when(builder.build()).thenReturn(data);
+    }
+
+    protected abstract GenericReader<DataObject,Builder<DataObject>> initReader();
+
+    protected GenericReader<DataObject, Builder<DataObject>> getReader() {
+        return reader;
+    }
+
+    protected ReaderCustomizer<DataObject, Builder<DataObject>> getCustomizer() {
+        return customizer;
+    }
+
+    @Test
+    public void testGetBuilder() throws Exception {
+        assertEquals(builder, reader.getBuilder(DATA_OBJECT_ID));
+        verify(customizer).getBuilder(DATA_OBJECT_ID);
+    }
+
+    @Test
+    public void testManagedType() throws Exception {
+        assertEquals(DATA_OBJECT_ID, reader.getManagedDataObjectType());
+    }
+
+    @Test
+    public void testMerge() throws Exception {
+        reader.merge(builder, data);
+        verify(customizer).merge(builder, data);
+    }
+
+    @Test
+    public void testRead() throws Exception {
+        reader.read(DATA_OBJECT_ID, ctx);
+
+        verify(customizer).getBuilder(DATA_OBJECT_ID);
+        verify(customizer).readCurrentAttributes(DATA_OBJECT_ID, builder, ctx);
+    }
+}
\ No newline at end of file
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericInitListReaderTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericInitListReaderTest.java
new file mode 100644 (file)
index 0000000..f695e66
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2017 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.translate.impl.read;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.read.InitFailedException;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingListReaderCustomizer;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.concepts.Builder;
+
+public class GenericInitListReaderTest extends AbstractListReaderTest {
+
+    @Mock
+    private DataBroker broker;
+    @Mock
+    private WriteTransaction writeTx;
+
+    public GenericInitListReaderTest() {
+        super(InitializingListReaderCustomizer.class);
+    }
+
+    @Override
+    protected GenericListReader<AbstractListReaderTest.TestingData, AbstractListReaderTest.TestingData.TestingKey, Builder<AbstractListReaderTest.TestingData>> initReader() {
+        return new GenericInitListReader<>(DATA_OBJECT_ID, getCustomizer());
+    }
+
+    @Override
+    protected InitializingListReaderCustomizer<AbstractListReaderTest.TestingData, AbstractListReaderTest.TestingData.TestingKey, Builder<AbstractListReaderTest.TestingData>> getCustomizer() {
+        return (InitializingListReaderCustomizer<AbstractListReaderTest.TestingData, AbstractListReaderTest.TestingData.TestingKey, Builder<AbstractListReaderTest.TestingData>>) super
+            .getCustomizer();
+    }
+
+    @Override
+    public GenericInitListReader<AbstractListReaderTest.TestingData, AbstractListReaderTest.TestingData.TestingKey, Builder<AbstractListReaderTest.TestingData>> getReader() {
+        return (GenericInitListReader<AbstractListReaderTest.TestingData, AbstractListReaderTest.TestingData.TestingKey, Builder<AbstractListReaderTest.TestingData>>) super
+            .getReader();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testInit() throws Exception {
+        final Initialized<TestingData> initialized = Initialized.create(DATA_OBJECT_ID, data);
+        when(getCustomizer().isPresent(any(), any(), any())).thenReturn(true);
+        doReturn(initialized).when(getCustomizer()).init(any(), any(), any());
+        when(broker.newWriteOnlyTransaction()).thenReturn(writeTx);
+
+        getReader().init(broker, DATA_OBJECT_ID, ctx);
+
+        verify(writeTx, times(2)).merge(LogicalDatastoreType.CONFIGURATION, DATA_OBJECT_ID, data, true);
+        verify(writeTx, times(2)).submit();
+    }
+
+    @Test(expected = InitFailedException.class)
+    public void testInitFailed() throws Exception {
+        doThrow(new ReadFailedException(DATA_OBJECT_ID)).when(getCustomizer())
+            .readCurrentAttributes(any(), any(), any());
+
+        getReader().init(broker, DATA_OBJECT_ID, ctx);
+
+        verifyZeroInteractions(writeTx);
+    }
+}
\ No newline at end of file
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericIntReaderTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/GenericIntReaderTest.java
new file mode 100644 (file)
index 0000000..ef3de45
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017 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.translate.impl.read;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import io.fd.honeycomb.translate.read.InitFailedException;
+import io.fd.honeycomb.translate.read.ReadFailedException;
+import io.fd.honeycomb.translate.spi.read.Initialized;
+import io.fd.honeycomb.translate.spi.read.InitializingReaderCustomizer;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public class GenericIntReaderTest extends AbstractReaderTest {
+
+    @Mock
+    private DataBroker broker;
+    @Mock
+    private WriteTransaction writeTx;
+
+    public GenericIntReaderTest() {
+        super(InitializingReaderCustomizer.class);
+    }
+
+    @Override
+    protected GenericReader<DataObject, Builder<DataObject>> initReader() {
+        return new GenericInitReader<>(DATA_OBJECT_ID, getCustomizer());
+    }
+
+    @Override
+    public GenericInitReader<DataObject, Builder<DataObject>> getReader() {
+        return (GenericInitReader<DataObject, Builder<DataObject>>)super.getReader();
+    }
+
+    @Override
+    public InitializingReaderCustomizer<DataObject, Builder<DataObject>> getCustomizer() {
+        return (InitializingReaderCustomizer<DataObject, Builder<DataObject>>)super.getCustomizer();
+    }
+
+    @Test
+    public void testInit() throws Exception {
+        final Initialized<DataObject> initialized = Initialized.create(DATA_OBJECT_ID, data);
+
+        when(getCustomizer().isPresent(DATA_OBJECT_ID, data, ctx)).thenReturn(true);
+        doReturn(initialized).when(getCustomizer()).init(DATA_OBJECT_ID, data, ctx);
+        when(broker.newWriteOnlyTransaction()).thenReturn(writeTx);
+
+        getReader().init(broker, DATA_OBJECT_ID, ctx);
+
+        verify(writeTx).merge(LogicalDatastoreType.CONFIGURATION, DATA_OBJECT_ID, data, true);
+        verify(writeTx).submit();
+    }
+
+    @Test(expected = InitFailedException.class)
+    public void testInitFailed() throws Exception {
+        doThrow(new ReadFailedException(DATA_OBJECT_ID)).when(getCustomizer())
+            .readCurrentAttributes(DATA_OBJECT_ID, builder, ctx);
+
+        getReader().init(broker, DATA_OBJECT_ID, ctx);
+
+        verifyZeroInteractions(writeTx);
+    }
+}
\ No newline at end of file
index 3ed400d..d3959ed 100644 (file)
 
 package io.fd.honeycomb.translate.impl.read;
 
-import static org.junit.Assert.assertEquals;
-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.Lists;
-import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.spi.read.ListReaderCustomizer;
-import java.util.List;
-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.DataContainer;
-import org.opendaylight.yangtools.yang.binding.DataObject;
-import org.opendaylight.yangtools.yang.binding.Identifiable;
-import org.opendaylight.yangtools.yang.binding.Identifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class GenericListReaderTest {
-
-    private static final InstanceIdentifier<TestingData>
-            DATA_OBJECT_ID = InstanceIdentifier.create(TestingData.class);
-    @Mock
-    private ListReaderCustomizer<TestingData, TestingData.TestingKey, Builder<TestingData>> customizer;
-    @Mock
-    private Builder<TestingData> builder;
-    @Mock
-    private TestingData data;
-    @Mock
-    private ReadContext ctx;
-    private GenericListReader<TestingData, TestingData.TestingKey, Builder<TestingData>> reader;
-    private List<TestingData.TestingKey> keys = Lists.newArrayList(new TestingData.TestingKey(),
-            new TestingData.TestingKey());
-
-    @SuppressWarnings("unchecked")
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        when(customizer.getBuilder(any(InstanceIdentifier.class))).thenReturn(builder);
-        when(customizer.getAllIds(DATA_OBJECT_ID, ctx)).thenReturn(keys);
-        reader = new GenericListReader<>(DATA_OBJECT_ID, customizer);
-        when(builder.build()).thenReturn(data);
-    }
 
-    @Test
-    public void testGetBuilder() throws Exception {
-        assertEquals(builder, reader.getBuilder(DATA_OBJECT_ID));
-        verify(customizer).getBuilder(DATA_OBJECT_ID);
-    }
-
-    @Test
-    public void testManagedType() throws Exception {
-        assertEquals(DATA_OBJECT_ID, reader.getManagedDataObjectType());
-    }
-
-    @Test
-    public void testMerge() throws Exception {
-        reader.merge(builder, data);
-        verify(customizer).merge(builder, data);
-    }
+public class GenericListReaderTest extends AbstractListReaderTest {
 
-    @Test
-    public void testAllIds() throws Exception {
-        assertEquals(keys, reader.getAllIds(DATA_OBJECT_ID, ctx));
-        verify(customizer).getAllIds(DATA_OBJECT_ID, ctx);
+    public GenericListReaderTest() {
+        super(ListReaderCustomizer.class);
     }
 
-    @Test
-    public void testRead() throws Exception {
-        reader.read(DATA_OBJECT_ID, ctx);
-
-        verify(customizer).getBuilder(DATA_OBJECT_ID);
-        verify(customizer).readCurrentAttributes(DATA_OBJECT_ID, builder, ctx);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testReadList() throws Exception {
-        reader.readList(DATA_OBJECT_ID, ctx);
-
-        verify(customizer, times(2)).getBuilder(any(InstanceIdentifier.class));
-        verify(customizer, times(2))
-                .readCurrentAttributes(any(InstanceIdentifier.class), any(Builder.class), any(ReadContext.class));
-    }
-
-    static class TestingData implements DataObject, Identifiable<TestingData.TestingKey> {
-
-        @Override
-        public Class<? extends DataContainer> getImplementedInterface() {
-            return DataObject.class;
-        }
-
-        @Override
-        public TestingKey getKey() {
-            return new TestingKey();
-        }
-
-        static class TestingKey implements Identifier<TestingData> {}
+    @Override
+    protected GenericListReader<TestingData, TestingData.TestingKey, Builder<TestingData>> initReader() {
+        return new GenericListReader<>(DATA_OBJECT_ID, getCustomizer());
     }
 }
\ No newline at end of file
index 02baab2..7b999be 100644 (file)
 
 package io.fd.honeycomb.translate.impl.read;
 
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import io.fd.honeycomb.translate.read.ReadContext;
 import io.fd.honeycomb.translate.spi.read.ReaderCustomizer;
-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.DataObject;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-
-public class GenericReaderTest {
 
-    private static final InstanceIdentifier<DataObject>
-            DATA_OBJECT_ID = InstanceIdentifier.create(DataObject.class);
-    @Mock
-    private ReaderCustomizer<DataObject, Builder<DataObject>> customizer;
-    @Mock
-    private Builder<DataObject> builder;
-    @Mock
-    private DataObject data;
-    @Mock
-    private ReadContext ctx;
-    private GenericReader<DataObject, Builder<DataObject>> reader;
+public class GenericReaderTest extends AbstractReaderTest {
 
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        when(customizer.getBuilder(DATA_OBJECT_ID)).thenReturn(builder);
-        reader = new GenericReader<>(DATA_OBJECT_ID, customizer);
-        when(builder.build()).thenReturn(data);
+    public GenericReaderTest() {
+        super(ReaderCustomizer.class);
     }
 
-    @Test
-    public void testGetBuilder() throws Exception {
-        assertEquals(builder, reader.getBuilder(DATA_OBJECT_ID));
-        verify(customizer).getBuilder(DATA_OBJECT_ID);
-    }
-
-    @Test
-    public void testManagedType() throws Exception {
-        assertEquals(DATA_OBJECT_ID, reader.getManagedDataObjectType());
-    }
-
-    @Test
-    public void testMerge() throws Exception {
-        reader.merge(builder, data);
-        verify(customizer).merge(builder, data);
-    }
-
-    @Test
-    public void testRead() throws Exception {
-        reader.read(DATA_OBJECT_ID, ctx);
-
-        verify(customizer).getBuilder(DATA_OBJECT_ID);
-        verify(customizer).readCurrentAttributes(DATA_OBJECT_ID, builder, ctx);
+    @Override
+    protected GenericReader<DataObject,Builder<DataObject>> initReader() {
+        return new GenericReader<>(DATA_OBJECT_ID, getCustomizer());
     }
 }
\ No newline at end of file
diff --git a/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/registry/InitSubtreeReaderTest.java b/infra/translate-impl/src/test/java/io/fd/honeycomb/translate/impl/read/registry/InitSubtreeReaderTest.java
new file mode 100644 (file)
index 0000000..a9b15ad
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2017 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.translate.impl.read.registry;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import com.google.common.collect.Sets;
+import io.fd.honeycomb.translate.read.InitListReader;
+import io.fd.honeycomb.translate.read.InitReader;
+import io.fd.honeycomb.translate.read.ListReader;
+import io.fd.honeycomb.translate.read.ReadContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InitSubtreeReaderTest {
+
+    @Mock
+    private DataBroker broker;
+    @Mock
+    private InitReader<DataObject1, Builder<DataObject1>> delegate;
+    @Mock
+    private InitListReader<DataObject2, DataObject2.DataObject2Key, Builder<DataObject2>> listDelegate;
+    @Mock
+    private ReadContext ctx;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn(DataObject1.IID).when(delegate).getManagedDataObjectType();
+        doReturn(DataObject2.IID).when(listDelegate).getManagedDataObjectType();
+    }
+
+    @Test
+    public void testInit() throws Exception {
+        final InitReader<DataObject1, Builder<DataObject1>> initSubReader =
+            InitSubtreeReader.createForReader(Sets.newHashSet(DataObject1.DataObject11.IID), delegate);
+        assertFalse(initSubReader instanceof ListReader);
+
+        initSubReader.init(broker, DataObject1.IID, ctx);
+        verify(delegate).init(broker, DataObject1.IID, ctx);
+    }
+
+    @Test
+    public void testInitList() throws Exception {
+        final InitReader<DataObject2, Builder<DataObject2>> initSubReader =
+            InitSubtreeReader.createForReader(Sets.newHashSet(DataObject2.DataObject22.IID), listDelegate);
+        assertTrue(initSubReader instanceof ListReader);
+
+        initSubReader.init(broker, DataObject2.IID, ctx);
+        verify(listDelegate).init(broker, DataObject2.IID, ctx);
+    }
+
+    private abstract static class DataObject1 implements DataObject {
+        private static InstanceIdentifier<DataObject1> IID = InstanceIdentifier.create(DataObject1.class);
+        private abstract static class DataObject11 implements DataObject, ChildOf<DataObject1> {
+            private static InstanceIdentifier<DataObject11> IID = DataObject1.IID.child(DataObject11.class);
+        }
+    }
+
+    private abstract static class DataObject2 implements Identifiable<DataObject2.DataObject2Key>, DataObject {
+        private static InstanceIdentifier<DataObject2> IID = InstanceIdentifier.create(DataObject2.class);
+        abstract static class DataObject2Key implements Identifier<DataObject2> {
+        }
+        private abstract static class DataObject22 implements DataObject, ChildOf<DataObject2> {
+            public static InstanceIdentifier<DataObject22> IID = DataObject2.IID.child(DataObject22.class);
+        }
+    }
+}
\ No newline at end of file