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.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 testSingleUpdate() throws Exception {
53 final FlatWriterRegistry flatWriterRegistry =
54 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1));
56 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
57 final DataObject1 before = mock(DataObject1.class);
58 final DataObject1 after = mock(DataObject1.class);
59 flatWriterRegistry.update(iid, before, after, ctx);
61 verify(writer1).update(iid, before, after, ctx);
65 public void testMultipleUpdatesForSingleWriter() throws Exception {
66 final FlatWriterRegistry flatWriterRegistry =
67 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
69 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
70 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
71 final InstanceIdentifier<DataObject1> iid2 = InstanceIdentifier.create(DataObject1.class);
72 final DataObject1 dataObject = mock(DataObject1.class);
73 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
74 updates.put(DataObject1.IID, DataObjectUpdate.create(iid2, dataObject, dataObject));
75 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
77 verify(writer1).update(iid, dataObject, dataObject, ctx);
78 verify(writer1).update(iid2, dataObject, dataObject, ctx);
79 // Invoked when registry is being created
80 verifyNoMoreInteractions(writer1);
81 verifyZeroInteractions(writer2);
85 public void testMultipleUpdatesForMultipleWriters() throws Exception {
86 final FlatWriterRegistry flatWriterRegistry =
87 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
89 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
90 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
91 final DataObject1 dataObject = mock(DataObject1.class);
92 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
93 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
94 final DataObject2 dataObject2 = mock(DataObject2.class);
95 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
96 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
98 final InOrder inOrder = inOrder(writer1, writer2);
99 inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
100 inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
102 verifyNoMoreInteractions(writer1);
103 verifyNoMoreInteractions(writer2);
107 public void testMultipleDeletesForMultipleWriters() throws Exception {
108 final FlatWriterRegistry flatWriterRegistry =
109 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
111 final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
112 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
113 final DataObject1 dataObject = mock(DataObject1.class);
114 deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
115 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
116 final DataObject2 dataObject2 = mock(DataObject2.class);
117 deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
118 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(ImmutableMultimap.of(), deletes), ctx);
120 final InOrder inOrder = inOrder(writer1, writer2);
121 // Reversed order of invocation, first writer2 and then writer1
122 inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
123 inOrder.verify(writer1).update(iid, dataObject, null, ctx);
125 verifyNoMoreInteractions(writer1);
126 verifyNoMoreInteractions(writer2);
130 public void testMultipleUpdatesAndDeletesForMultipleWriters() throws Exception {
131 final FlatWriterRegistry flatWriterRegistry =
132 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
134 final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
135 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
136 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
137 final DataObject1 dataObject = mock(DataObject1.class);
139 deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
141 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
142 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
143 final DataObject2 dataObject2 = mock(DataObject2.class);
145 deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
147 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
148 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, deletes), ctx);
150 final InOrder inOrder = inOrder(writer1, writer2);
151 // Reversed order of invocation, first writer2 and then writer1 for deletes
152 inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
153 inOrder.verify(writer1).update(iid, dataObject, null, ctx);
154 // Then also updates are processed
155 inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
156 inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
158 verifyNoMoreInteractions(writer1);
159 verifyNoMoreInteractions(writer2);
162 @Test(expected = IllegalArgumentException.class)
163 public void testMultipleUpdatesOneMissing() throws Exception {
164 final FlatWriterRegistry flatWriterRegistry =
165 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1));
167 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
168 addUpdate(updates, DataObject1.class);
169 addUpdate(updates, DataObject2.class);
170 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
174 public void testMultipleUpdatesOneFailing() throws Exception {
175 final FlatWriterRegistry flatWriterRegistry =
176 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
178 // Writer1 always fails
179 doThrow(new RuntimeException()).when(writer1)
180 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
182 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
183 addUpdate(updates, DataObject1.class);
184 addUpdate(updates, DataObject2.class);
187 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
188 fail("Bulk update should have failed on writer1");
189 } catch (WriterRegistry.BulkUpdateException e) {
190 assertThat(e.getFailedIds().size(), is(2));
191 assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject2.class)));
192 assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject1.class)));
197 public void testMultipleUpdatesOneFailingThenRevertWithSuccess() throws Exception {
198 final FlatWriterRegistry flatWriterRegistry =
199 new FlatWriterRegistry(
200 ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
202 // Writer1 always fails
203 doThrow(new RuntimeException()).when(writer3)
204 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
206 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
207 addUpdate(updates, DataObject1.class);
208 addUpdate(updates, DataObject3.class);
209 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
210 final DataObject2 before2 = mock(DataObject2.class);
211 final DataObject2 after2 = mock(DataObject2.class);
212 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, before2, after2));
215 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
216 fail("Bulk update should have failed on writer1");
217 } catch (WriterRegistry.BulkUpdateException e) {
218 assertThat(e.getFailedIds().size(), is(1));
220 final InOrder inOrder = inOrder(writer1, writer2, writer3);
221 inOrder.verify(writer1)
222 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
223 inOrder.verify(writer2)
224 .update(iid2, before2, after2, ctx);
225 inOrder.verify(writer3)
226 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
229 // Revert changes. Successful updates are iterated in reverse
230 inOrder.verify(writer2)
231 .update(iid2, after2, before2, ctx);
232 inOrder.verify(writer1)
233 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
234 verifyNoMoreInteractions(writer3);
239 public void testMultipleUpdatesOneFailingThenRevertWithFail() throws Exception {
240 final FlatWriterRegistry flatWriterRegistry =
241 new FlatWriterRegistry(
242 ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
244 // Writer1 always fails
245 doThrow(new RuntimeException()).when(writer3)
246 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
248 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
249 addUpdate(updates, DataObject1.class);
250 addUpdate(updates, DataObject2.class);
251 addUpdate(updates, DataObject3.class);
254 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
255 fail("Bulk update should have failed on writer1");
256 } catch (WriterRegistry.BulkUpdateException e) {
257 // Writer1 always fails from now
258 doThrow(new RuntimeException()).when(writer1)
259 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
262 } catch (WriterRegistry.Reverter.RevertFailedException e1) {
263 assertThat(e1.getNotRevertedChanges().size(), is(1));
264 assertThat(e1.getNotRevertedChanges(), hasItem(InstanceIdentifier.create(DataObject1.class)));
269 private <D extends DataObject> void addUpdate(final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates,
270 final Class<D> type) throws Exception {
271 final InstanceIdentifier<D> iid = (InstanceIdentifier<D>) type.getDeclaredField("IID").get(null);
272 updates.put(iid, DataObjectUpdate.create(iid, mock(type), mock(type)));
275 @Test(expected = IllegalArgumentException.class)
276 public void testSingleUpdateMissingWriter() throws Exception {
277 final FlatWriterRegistry flatWriterRegistry =
278 new FlatWriterRegistry(ImmutableMap.of());
280 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
281 final DataObject1 before = mock(DataObject1.class);
282 final DataObject1 after = mock(DataObject1.class);
283 flatWriterRegistry.update(iid, before, after, ctx);
286 private abstract static class DataObject1 implements DataObject {
287 static final InstanceIdentifier<DataObject1> IID = InstanceIdentifier.create(DataObject1.class);
289 private abstract static class DataObject2 implements DataObject {
290 static final InstanceIdentifier<DataObject2> IID = InstanceIdentifier.create(DataObject2.class);
292 private abstract static class DataObject3 implements DataObject {
293 static final InstanceIdentifier<DataObject3> IID = InstanceIdentifier.create(DataObject3.class);