Merge "Make Raft messages serializable"
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / ShardTransactionTest.java
1 package org.opendaylight.controller.cluster.datastore;
2
3 import akka.actor.ActorRef;
4 import akka.actor.Props;
5 import akka.actor.Terminated;
6 import akka.testkit.JavaTestKit;
7 import com.google.common.util.concurrent.ListeningExecutorService;
8 import com.google.common.util.concurrent.MoreExecutors;
9 import org.junit.Test;
10 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
11 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
12 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
13 import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
14 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
15 import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
16 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
17 import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
18 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
19 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
20 import org.opendaylight.controller.cluster.datastore.messages.WriteData;
21 import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
22 import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
23 import org.opendaylight.controller.cluster.datastore.modification.DeleteModification;
24 import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
25 import org.opendaylight.controller.cluster.datastore.modification.Modification;
26 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
27 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
28 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
30 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32
33 import static org.junit.Assert.assertEquals;
34 import static org.junit.Assert.assertTrue;
35
36 public class ShardTransactionTest extends AbstractActorTest {
37     private static ListeningExecutorService storeExecutor =
38         MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
39
40     private static final InMemoryDOMDataStore store =
41         new InMemoryDOMDataStore("OPER", storeExecutor);
42
43     private static final SchemaContext testSchemaContext = TestModel.createTestContext();
44
45     static {
46         store.onGlobalContextUpdated(testSchemaContext);
47     }
48
49     @Test
50     public void testOnReceiveReadData() throws Exception {
51         new JavaTestKit(getSystem()) {{
52             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
53             final Props props =
54                 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
55             final ActorRef subject = getSystem().actorOf(props, "testReadData");
56
57             new Within(duration("1 seconds")) {
58                 protected void run() {
59
60                     subject.tell(
61                         new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
62                         getRef());
63
64                     final String out = new ExpectMsg<String>("match hint") {
65                         // do not put code outside this method, will run afterwards
66                         protected String match(Object in) {
67                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
68                               if (ReadDataReply.fromSerializable(testSchemaContext,YangInstanceIdentifier.builder().build(), in)
69                                   .getNormalizedNode()!= null) {
70                                     return "match";
71                                 }
72                                 return null;
73                             } else {
74                                 throw noMatch();
75                             }
76                         }
77                     }.get(); // this extracts the received message
78
79                     assertEquals("match", out);
80
81                     expectNoMsg();
82                 }
83
84
85             };
86         }};
87     }
88
89     @Test
90     public void testOnReceiveReadDataWhenDataNotFound() throws Exception {
91         new JavaTestKit(getSystem()) {{
92             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
93             final Props props =
94                 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
95             final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
96
97             new Within(duration("1 seconds")) {
98                 protected void run() {
99
100                     subject.tell(
101                         new ReadData(TestModel.TEST_PATH).toSerializable(),
102                         getRef());
103
104                     final String out = new ExpectMsg<String>("match hint") {
105                         // do not put code outside this method, will run afterwards
106                         protected String match(Object in) {
107                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
108                                 if (ReadDataReply.fromSerializable(testSchemaContext,TestModel.TEST_PATH, in)
109                                     .getNormalizedNode()
110                                     == null) {
111                                     return "match";
112                                 }
113                                 return null;
114                             } else {
115                                 throw noMatch();
116                             }
117                         }
118                     }.get(); // this extracts the received message
119
120                     assertEquals("match", out);
121
122                     expectNoMsg();
123                 }
124
125
126             };
127         }};
128     }
129
130     private void assertModification(final ActorRef subject,
131         final Class<? extends Modification> modificationType) {
132         new JavaTestKit(getSystem()) {{
133             new Within(duration("1 seconds")) {
134                 protected void run() {
135                     subject
136                         .tell(new ShardTransaction.GetCompositedModification(),
137                             getRef());
138
139                     final CompositeModification compositeModification =
140                         new ExpectMsg<CompositeModification>("match hint") {
141                             // do not put code outside this method, will run afterwards
142                             protected CompositeModification match(Object in) {
143                                 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
144                                     return ((ShardTransaction.GetCompositeModificationReply) in)
145                                         .getModification();
146                                 } else {
147                                     throw noMatch();
148                                 }
149                             }
150                         }.get(); // this extracts the received message
151
152                     assertTrue(
153                         compositeModification.getModifications().size() == 1);
154                     assertEquals(modificationType,
155                         compositeModification.getModifications().get(0)
156                             .getClass());
157
158                 }
159             };
160         }};
161     }
162
163     @Test
164     public void testOnReceiveWriteData() throws Exception {
165         new JavaTestKit(getSystem()) {{
166             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
167             final Props props =
168                 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
169             final ActorRef subject =
170                 getSystem().actorOf(props, "testWriteData");
171
172             new Within(duration("1 seconds")) {
173                 protected void run() {
174
175                     subject.tell(new WriteData(TestModel.TEST_PATH,
176                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
177                         getRef());
178
179                     final String out = new ExpectMsg<String>("match hint") {
180                         // do not put code outside this method, will run afterwards
181                         protected String match(Object in) {
182                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
183                                 return "match";
184                             } else {
185                                 throw noMatch();
186                             }
187                         }
188                     }.get(); // this extracts the received message
189
190                     assertEquals("match", out);
191
192                     assertModification(subject, WriteModification.class);
193                     expectNoMsg();
194                 }
195
196
197             };
198         }};
199     }
200
201     @Test
202     public void testOnReceiveMergeData() throws Exception {
203         new JavaTestKit(getSystem()) {{
204             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
205             final Props props =
206                 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
207             final ActorRef subject =
208                 getSystem().actorOf(props, "testMergeData");
209
210             new Within(duration("1 seconds")) {
211                 protected void run() {
212
213                     subject.tell(new MergeData(TestModel.TEST_PATH,
214                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), testSchemaContext).toSerializable(),
215                         getRef());
216
217                     final String out = new ExpectMsg<String>(duration("500 milliseconds"), "match hint") {
218                         // do not put code outside this method, will run afterwards
219                         protected String match(Object in) {
220                             if (in.getClass().equals(MergeDataReply.SERIALIZABLE_CLASS)) {
221                                 return "match";
222                             } else {
223                                 throw noMatch();
224                             }
225                         }
226                     }.get(); // this extracts the received message
227
228                     assertEquals("match", out);
229
230                     assertModification(subject, MergeModification.class);
231
232                     expectNoMsg();
233                 }
234
235
236             };
237         }};
238     }
239
240     @Test
241     public void testOnReceiveDeleteData() throws Exception {
242         new JavaTestKit(getSystem()) {{
243             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
244             final Props props =
245                 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
246             final ActorRef subject =
247                 getSystem().actorOf(props, "testDeleteData");
248
249             new Within(duration("1 seconds")) {
250                 protected void run() {
251
252                     subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
253
254                     final String out = new ExpectMsg<String>("match hint") {
255                         // do not put code outside this method, will run afterwards
256                         protected String match(Object in) {
257                             if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
258                                 return "match";
259                             } else {
260                                 throw noMatch();
261                             }
262                         }
263                     }.get(); // this extracts the received message
264
265                     assertEquals("match", out);
266
267                     assertModification(subject, DeleteModification.class);
268                     expectNoMsg();
269                 }
270
271
272             };
273         }};
274     }
275
276
277     @Test
278     public void testOnReceiveReadyTransaction() throws Exception {
279         new JavaTestKit(getSystem()) {{
280             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
281             final Props props =
282                 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
283             final ActorRef subject =
284                 getSystem().actorOf(props, "testReadyTransaction");
285
286             new Within(duration("1 seconds")) {
287                 protected void run() {
288
289                     subject.tell(new ReadyTransaction().toSerializable(), getRef());
290
291                     final String out = new ExpectMsg<String>("match hint") {
292                         // do not put code outside this method, will run afterwards
293                         protected String match(Object in) {
294                             if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
295                                 return "match";
296                             } else {
297                                 throw noMatch();
298                             }
299                         }
300                     }.get(); // this extracts the received message
301
302                     assertEquals("match", out);
303
304                     expectNoMsg();
305                 }
306
307
308             };
309         }};
310
311     }
312
313     @Test
314     public void testOnReceiveCloseTransaction() throws Exception {
315         new JavaTestKit(getSystem()) {{
316             final ActorRef shard = getSystem().actorOf(Shard.props("config"));
317             final Props props =
318                 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
319             final ActorRef subject =
320                 getSystem().actorOf(props, "testCloseTransaction");
321
322             watch(subject);
323
324             new Within(duration("2 seconds")) {
325                 protected void run() {
326
327                     subject.tell(new CloseTransaction().toSerializable(), getRef());
328
329                     final String out = new ExpectMsg<String>("match hint") {
330                         // do not put code outside this method, will run afterwards
331                         protected String match(Object in) {
332                             if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
333                                 return "match";
334                             } else {
335                                 throw noMatch();
336                             }
337                         }
338                     }.get(); // this extracts the received message
339
340                     assertEquals("match", out);
341
342                     final String termination = new ExpectMsg<String>("match hint") {
343                         // do not put code outside this method, will run afterwards
344                         protected String match(Object in) {
345                             if (in instanceof Terminated) {
346                                 return "match";
347                             } else {
348                                 throw noMatch();
349                             }
350                         }
351                     }.get(); // this extracts the received message
352
353
354                     expectNoMsg();
355                 }
356
357
358             };
359         }};
360
361     }
362 }