1 package io.fd.honeycomb.v3po.translate.util.write.registry;
3 import static org.hamcrest.CoreMatchers.hasItem;
4 import static org.hamcrest.CoreMatchers.is;
5 import static org.junit.Assert.assertThat;
6 import static org.junit.Assert.fail;
7 import static org.mockito.Matchers.any;
8 import static org.mockito.Mockito.doThrow;
9 import static org.mockito.Mockito.inOrder;
10 import static org.mockito.Mockito.mock;
11 import static org.mockito.Mockito.verify;
12 import static org.mockito.Mockito.verifyNoMoreInteractions;
13 import static org.mockito.Mockito.verifyZeroInteractions;
14 import static org.mockito.Mockito.when;
16 import com.google.common.collect.HashMultimap;
17 import com.google.common.collect.ImmutableMap;
18 import com.google.common.collect.ImmutableMultimap;
19 import com.google.common.collect.Multimap;
20 import io.fd.honeycomb.v3po.translate.write.DataObjectUpdate;
21 import io.fd.honeycomb.v3po.translate.write.WriteContext;
22 import io.fd.honeycomb.v3po.translate.write.Writer;
23 import io.fd.honeycomb.v3po.translate.write.registry.WriterRegistry;
24 import org.junit.Before;
25 import org.junit.Test;
26 import org.mockito.InOrder;
27 import org.mockito.Mock;
28 import org.mockito.MockitoAnnotations;
29 import org.opendaylight.yangtools.yang.binding.DataObject;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 public class FlatWriterRegistryTest {
35 private Writer<DataObject1> writer1;
37 private Writer<DataObject2> writer2;
39 private Writer<DataObject3> writer3;
41 private WriteContext ctx;
44 public void setUp() throws Exception {
45 MockitoAnnotations.initMocks(this);
46 when(writer1.getManagedDataObjectType()).thenReturn(DataObject1.IID);
47 when(writer2.getManagedDataObjectType()).thenReturn(DataObject2.IID);
48 when(writer3.getManagedDataObjectType()).thenReturn(DataObject3.IID);
52 public void testMultipleUpdatesForSingleWriter() throws Exception {
53 final FlatWriterRegistry flatWriterRegistry =
54 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
56 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
57 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
58 final InstanceIdentifier<DataObject1> iid2 = InstanceIdentifier.create(DataObject1.class);
59 final DataObject1 dataObject = mock(DataObject1.class);
60 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
61 updates.put(DataObject1.IID, DataObjectUpdate.create(iid2, dataObject, dataObject));
62 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
64 verify(writer1).update(iid, dataObject, dataObject, ctx);
65 verify(writer1).update(iid2, dataObject, dataObject, ctx);
66 // Invoked when registry is being created
67 verifyNoMoreInteractions(writer1);
68 verifyZeroInteractions(writer2);
72 public void testMultipleUpdatesForMultipleWriters() throws Exception {
73 final FlatWriterRegistry flatWriterRegistry =
74 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
76 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
77 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
78 final DataObject1 dataObject = mock(DataObject1.class);
79 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
80 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
81 final DataObject2 dataObject2 = mock(DataObject2.class);
82 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
83 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
85 final InOrder inOrder = inOrder(writer1, writer2);
86 inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
87 inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
89 verifyNoMoreInteractions(writer1);
90 verifyNoMoreInteractions(writer2);
94 public void testMultipleDeletesForMultipleWriters() throws Exception {
95 final FlatWriterRegistry flatWriterRegistry =
96 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
98 final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
99 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
100 final DataObject1 dataObject = mock(DataObject1.class);
101 deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
102 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
103 final DataObject2 dataObject2 = mock(DataObject2.class);
104 deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
105 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(ImmutableMultimap.of(), deletes), ctx);
107 final InOrder inOrder = inOrder(writer1, writer2);
108 // Reversed order of invocation, first writer2 and then writer1
109 inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
110 inOrder.verify(writer1).update(iid, dataObject, null, ctx);
112 verifyNoMoreInteractions(writer1);
113 verifyNoMoreInteractions(writer2);
117 public void testMultipleUpdatesAndDeletesForMultipleWriters() throws Exception {
118 final FlatWriterRegistry flatWriterRegistry =
119 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
121 final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
122 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
123 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
124 final DataObject1 dataObject = mock(DataObject1.class);
126 deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
128 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
129 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
130 final DataObject2 dataObject2 = mock(DataObject2.class);
132 deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
134 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
135 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, deletes), ctx);
137 final InOrder inOrder = inOrder(writer1, writer2);
138 // Reversed order of invocation, first writer2 and then writer1 for deletes
139 inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
140 inOrder.verify(writer1).update(iid, dataObject, null, ctx);
141 // Then also updates are processed
142 inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
143 inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
145 verifyNoMoreInteractions(writer1);
146 verifyNoMoreInteractions(writer2);
149 @Test(expected = IllegalArgumentException.class)
150 public void testMultipleUpdatesOneMissing() throws Exception {
151 final FlatWriterRegistry flatWriterRegistry =
152 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1));
154 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
155 addUpdate(updates, DataObject1.class);
156 addUpdate(updates, DataObject2.class);
157 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
161 public void testMultipleUpdatesOneFailing() throws Exception {
162 final FlatWriterRegistry flatWriterRegistry =
163 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
165 // Writer1 always fails
166 doThrow(new RuntimeException()).when(writer1)
167 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
169 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
170 addUpdate(updates, DataObject1.class);
171 addUpdate(updates, DataObject2.class);
174 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
175 fail("Bulk update should have failed on writer1");
176 } catch (WriterRegistry.BulkUpdateException e) {
177 assertThat(e.getFailedIds().size(), is(2));
178 assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject2.class)));
179 assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject1.class)));
184 public void testMultipleUpdatesOneFailingThenRevertWithSuccess() throws Exception {
185 final FlatWriterRegistry flatWriterRegistry =
186 new FlatWriterRegistry(
187 ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
189 // Writer1 always fails
190 doThrow(new RuntimeException()).when(writer3)
191 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
193 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
194 addUpdate(updates, DataObject1.class);
195 addUpdate(updates, DataObject3.class);
196 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
197 final DataObject2 before2 = mock(DataObject2.class);
198 final DataObject2 after2 = mock(DataObject2.class);
199 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, before2, after2));
202 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
203 fail("Bulk update should have failed on writer1");
204 } catch (WriterRegistry.BulkUpdateException e) {
205 assertThat(e.getFailedIds().size(), is(1));
207 final InOrder inOrder = inOrder(writer1, writer2, writer3);
208 inOrder.verify(writer1)
209 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
210 inOrder.verify(writer2)
211 .update(iid2, before2, after2, ctx);
212 inOrder.verify(writer3)
213 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
216 // Revert changes. Successful updates are iterated in reverse
217 inOrder.verify(writer2)
218 .update(iid2, after2, before2, ctx);
219 inOrder.verify(writer1)
220 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
221 verifyNoMoreInteractions(writer3);
226 public void testMultipleUpdatesOneFailingThenRevertWithFail() throws Exception {
227 final FlatWriterRegistry flatWriterRegistry =
228 new FlatWriterRegistry(
229 ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
231 // Writer1 always fails
232 doThrow(new RuntimeException()).when(writer3)
233 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
235 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
236 addUpdate(updates, DataObject1.class);
237 addUpdate(updates, DataObject2.class);
238 addUpdate(updates, DataObject3.class);
241 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
242 fail("Bulk update should have failed on writer1");
243 } catch (WriterRegistry.BulkUpdateException e) {
244 // Writer1 always fails from now
245 doThrow(new RuntimeException()).when(writer1)
246 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
249 } catch (WriterRegistry.Reverter.RevertFailedException e1) {
250 assertThat(e1.getNotRevertedChanges().size(), is(1));
251 assertThat(e1.getNotRevertedChanges(), hasItem(InstanceIdentifier.create(DataObject1.class)));
256 private <D extends DataObject> void addUpdate(final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates,
257 final Class<D> type) throws Exception {
258 final InstanceIdentifier<D> iid = (InstanceIdentifier<D>) type.getDeclaredField("IID").get(null);
259 updates.put(iid, DataObjectUpdate.create(iid, mock(type), mock(type)));
262 private abstract static class DataObject1 implements DataObject {
263 static final InstanceIdentifier<DataObject1> IID = InstanceIdentifier.create(DataObject1.class);
265 private abstract static class DataObject2 implements DataObject {
266 static final InstanceIdentifier<DataObject2> IID = InstanceIdentifier.create(DataObject2.class);
268 private abstract static class DataObject3 implements DataObject {
269 static final InstanceIdentifier<DataObject3> IID = InstanceIdentifier.create(DataObject3.class);