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.util.DataObjects.DataObject1;
21 import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject2;
22 import io.fd.honeycomb.v3po.translate.util.DataObjects.DataObject3;
23 import io.fd.honeycomb.v3po.translate.write.DataObjectUpdate;
24 import io.fd.honeycomb.v3po.translate.write.WriteContext;
25 import io.fd.honeycomb.v3po.translate.write.Writer;
26 import io.fd.honeycomb.v3po.translate.write.registry.WriterRegistry;
27 import org.junit.Before;
28 import org.junit.Test;
29 import org.mockito.InOrder;
30 import org.mockito.Mock;
31 import org.mockito.MockitoAnnotations;
32 import org.opendaylight.yangtools.yang.binding.DataObject;
33 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 public class FlatWriterRegistryTest {
38 private Writer<DataObject1> writer1;
40 private Writer<DataObject2> writer2;
42 private Writer<DataObject3> writer3;
44 private WriteContext ctx;
47 public void setUp() throws Exception {
48 MockitoAnnotations.initMocks(this);
49 when(writer1.getManagedDataObjectType()).thenReturn(DataObject1.IID);
50 when(writer2.getManagedDataObjectType()).thenReturn(DataObject2.IID);
51 when(writer3.getManagedDataObjectType()).thenReturn(DataObject3.IID);
55 public void testMultipleUpdatesForSingleWriter() throws Exception {
56 final FlatWriterRegistry flatWriterRegistry =
57 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
59 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
60 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
61 final InstanceIdentifier<DataObject1> iid2 = InstanceIdentifier.create(DataObject1.class);
62 final DataObject1 dataObject = mock(DataObject1.class);
63 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
64 updates.put(DataObject1.IID, DataObjectUpdate.create(iid2, dataObject, dataObject));
65 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
67 verify(writer1).update(iid, dataObject, dataObject, ctx);
68 verify(writer1).update(iid2, dataObject, dataObject, ctx);
69 // Invoked when registry is being created
70 verifyNoMoreInteractions(writer1);
71 verifyZeroInteractions(writer2);
75 public void testMultipleUpdatesForMultipleWriters() throws Exception {
76 final FlatWriterRegistry flatWriterRegistry =
77 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
79 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
80 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
81 final DataObject1 dataObject = mock(DataObject1.class);
82 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
83 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
84 final DataObject2 dataObject2 = mock(DataObject2.class);
85 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
86 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
88 final InOrder inOrder = inOrder(writer1, writer2);
89 inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
90 inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
92 verifyNoMoreInteractions(writer1);
93 verifyNoMoreInteractions(writer2);
97 public void testMultipleDeletesForMultipleWriters() throws Exception {
98 final FlatWriterRegistry flatWriterRegistry =
99 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
101 final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
102 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
103 final DataObject1 dataObject = mock(DataObject1.class);
104 deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
105 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
106 final DataObject2 dataObject2 = mock(DataObject2.class);
107 deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
108 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(ImmutableMultimap.of(), deletes), ctx);
110 final InOrder inOrder = inOrder(writer1, writer2);
111 // Reversed order of invocation, first writer2 and then writer1
112 inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
113 inOrder.verify(writer1).update(iid, dataObject, null, ctx);
115 verifyNoMoreInteractions(writer1);
116 verifyNoMoreInteractions(writer2);
120 public void testMultipleUpdatesAndDeletesForMultipleWriters() throws Exception {
121 final FlatWriterRegistry flatWriterRegistry =
122 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
124 final Multimap<InstanceIdentifier<?>, DataObjectUpdate.DataObjectDelete> deletes = HashMultimap.create();
125 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
126 final InstanceIdentifier<DataObject1> iid = InstanceIdentifier.create(DataObject1.class);
127 final DataObject1 dataObject = mock(DataObject1.class);
129 deletes.put(DataObject1.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid, dataObject, null)));
131 updates.put(DataObject1.IID, DataObjectUpdate.create(iid, dataObject, dataObject));
132 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
133 final DataObject2 dataObject2 = mock(DataObject2.class);
135 deletes.put(DataObject2.IID, ((DataObjectUpdate.DataObjectDelete) DataObjectUpdate.create(iid2, dataObject2, null)));
137 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, dataObject2, dataObject2));
138 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, deletes), ctx);
140 final InOrder inOrder = inOrder(writer1, writer2);
141 // Reversed order of invocation, first writer2 and then writer1 for deletes
142 inOrder.verify(writer2).update(iid2, dataObject2, null, ctx);
143 inOrder.verify(writer1).update(iid, dataObject, null, ctx);
144 // Then also updates are processed
145 inOrder.verify(writer1).update(iid, dataObject, dataObject, ctx);
146 inOrder.verify(writer2).update(iid2, dataObject2, dataObject2, ctx);
148 verifyNoMoreInteractions(writer1);
149 verifyNoMoreInteractions(writer2);
152 @Test(expected = IllegalArgumentException.class)
153 public void testMultipleUpdatesOneMissing() throws Exception {
154 final FlatWriterRegistry flatWriterRegistry =
155 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1));
157 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
158 addUpdate(updates, DataObject1.class);
159 addUpdate(updates, DataObject2.class);
160 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
164 public void testMultipleUpdatesOneFailing() throws Exception {
165 final FlatWriterRegistry flatWriterRegistry =
166 new FlatWriterRegistry(ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2));
168 // Writer1 always fails
169 doThrow(new RuntimeException()).when(writer1)
170 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
172 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
173 addUpdate(updates, DataObject1.class);
174 addUpdate(updates, DataObject2.class);
177 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
178 fail("Bulk update should have failed on writer1");
179 } catch (WriterRegistry.BulkUpdateException e) {
180 assertThat(e.getFailedIds().size(), is(2));
181 assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject2.class)));
182 assertThat(e.getFailedIds(), hasItem(InstanceIdentifier.create(DataObject1.class)));
187 public void testMultipleUpdatesOneFailingThenRevertWithSuccess() throws Exception {
188 final FlatWriterRegistry flatWriterRegistry =
189 new FlatWriterRegistry(
190 ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
192 // Writer1 always fails
193 doThrow(new RuntimeException()).when(writer3)
194 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
196 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
197 addUpdate(updates, DataObject1.class);
198 addUpdate(updates, DataObject3.class);
199 final InstanceIdentifier<DataObject2> iid2 = InstanceIdentifier.create(DataObject2.class);
200 final DataObject2 before2 = mock(DataObject2.class);
201 final DataObject2 after2 = mock(DataObject2.class);
202 updates.put(DataObject2.IID, DataObjectUpdate.create(iid2, before2, after2));
205 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
206 fail("Bulk update should have failed on writer1");
207 } catch (WriterRegistry.BulkUpdateException e) {
208 assertThat(e.getFailedIds().size(), is(1));
210 final InOrder inOrder = inOrder(writer1, writer2, writer3);
211 inOrder.verify(writer1)
212 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
213 inOrder.verify(writer2)
214 .update(iid2, before2, after2, ctx);
215 inOrder.verify(writer3)
216 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
219 // Revert changes. Successful updates are iterated in reverse
220 inOrder.verify(writer2)
221 .update(iid2, after2, before2, ctx);
222 inOrder.verify(writer1)
223 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
224 verifyNoMoreInteractions(writer3);
229 public void testMultipleUpdatesOneFailingThenRevertWithFail() throws Exception {
230 final FlatWriterRegistry flatWriterRegistry =
231 new FlatWriterRegistry(
232 ImmutableMap.of(DataObject1.IID, writer1, DataObject2.IID, writer2, DataObject3.IID, writer3));
234 // Writer1 always fails
235 doThrow(new RuntimeException()).when(writer3)
236 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
238 final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates = HashMultimap.create();
239 addUpdate(updates, DataObject1.class);
240 addUpdate(updates, DataObject2.class);
241 addUpdate(updates, DataObject3.class);
244 flatWriterRegistry.update(new WriterRegistry.DataObjectUpdates(updates, ImmutableMultimap.of()), ctx);
245 fail("Bulk update should have failed on writer1");
246 } catch (WriterRegistry.BulkUpdateException e) {
247 // Writer1 always fails from now
248 doThrow(new RuntimeException()).when(writer1)
249 .update(any(InstanceIdentifier.class), any(DataObject.class), any(DataObject.class), any(WriteContext.class));
252 } catch (WriterRegistry.Reverter.RevertFailedException e1) {
253 assertThat(e1.getNotRevertedChanges().size(), is(1));
254 assertThat(e1.getNotRevertedChanges(), hasItem(InstanceIdentifier.create(DataObject1.class)));
259 private <D extends DataObject> void addUpdate(final Multimap<InstanceIdentifier<?>, DataObjectUpdate> updates,
260 final Class<D> type) throws Exception {
261 final InstanceIdentifier<D> iid = (InstanceIdentifier<D>) type.getDeclaredField("IID").get(null);
262 updates.put(iid, DataObjectUpdate.create(iid, mock(type), mock(type)));