Merge "Bug 1430: Obtain config params from config system"
[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 akka.testkit.TestActorRef;
8 import com.google.common.util.concurrent.ListeningExecutorService;
9 import com.google.common.util.concurrent.MoreExecutors;
10 import org.junit.Assert;
11 import org.junit.Test;
12 import org.opendaylight.controller.cluster.datastore.exceptions.UnknownMessageException;
13 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
14 import org.opendaylight.controller.cluster.datastore.messages.CloseTransaction;
15 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionReply;
16 import org.opendaylight.controller.cluster.datastore.messages.DataExists;
17 import org.opendaylight.controller.cluster.datastore.messages.DataExistsReply;
18 import org.opendaylight.controller.cluster.datastore.messages.DeleteData;
19 import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
20 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
21 import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
22 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
23 import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
24 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
25 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
26 import org.opendaylight.controller.cluster.datastore.messages.WriteData;
27 import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
28 import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
29 import org.opendaylight.controller.cluster.datastore.modification.DeleteModification;
30 import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
31 import org.opendaylight.controller.cluster.datastore.modification.Modification;
32 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
33 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
34 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
37 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
38
39 import java.util.Collections;
40
41 import static org.junit.Assert.assertEquals;
42 import static org.junit.Assert.assertTrue;
43
44 public class ShardTransactionTest extends AbstractActorTest {
45     private static ListeningExecutorService storeExecutor =
46         MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
47
48     private static final InMemoryDOMDataStore store =
49         new InMemoryDOMDataStore("OPER", storeExecutor, MoreExecutors.sameThreadExecutor());
50
51     private static final SchemaContext testSchemaContext = TestModel.createTestContext();
52
53     private static final ShardIdentifier SHARD_IDENTIFIER =
54         ShardIdentifier.builder().memberName("member-1")
55             .shardName("inventory").type("config").build();
56
57
58     static {
59         store.onGlobalContextUpdated(testSchemaContext);
60     }
61
62     @Test
63     public void testOnReceiveReadData() throws Exception {
64         new JavaTestKit(getSystem()) {{
65             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
66             final Props props =
67                 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
68             final ActorRef subject = getSystem().actorOf(props, "testReadData");
69
70             new Within(duration("1 seconds")) {
71                 @Override
72                 protected void run() {
73
74                     subject.tell(
75                         new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
76                         getRef());
77
78                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
79                         // do not put code outside this method, will run afterwards
80                         @Override
81                         protected String match(Object in) {
82                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
83                               if (ReadDataReply.fromSerializable(testSchemaContext,YangInstanceIdentifier.builder().build(), in)
84                                   .getNormalizedNode()!= null) {
85                                     return "match";
86                                 }
87                                 return null;
88                             } else {
89                                 throw noMatch();
90                             }
91                         }
92                     }.get(); // this extracts the received message
93
94                     assertEquals("match", out);
95
96                     expectNoMsg();
97                 }
98
99
100             };
101         }};
102     }
103
104     @Test
105     public void testOnReceiveReadDataWhenDataNotFound() throws Exception {
106         new JavaTestKit(getSystem()) {{
107             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
108             final Props props =
109                 ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
110             final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
111
112             new Within(duration("1 seconds")) {
113                 @Override
114                 protected void run() {
115
116                     subject.tell(
117                         new ReadData(TestModel.TEST_PATH).toSerializable(),
118                         getRef());
119
120                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
121                         // do not put code outside this method, will run afterwards
122                         @Override
123                         protected String match(Object in) {
124                             if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
125                                 if (ReadDataReply.fromSerializable(testSchemaContext,TestModel.TEST_PATH, in)
126                                     .getNormalizedNode()
127                                     == null) {
128                                     return "match";
129                                 }
130                                 return null;
131                             } else {
132                                 throw noMatch();
133                             }
134                         }
135                     }.get(); // this extracts the received message
136
137                     assertEquals("match", out);
138
139                     expectNoMsg();
140                 }
141
142
143             };
144         }};
145     }
146
147     @Test
148     public void testOnReceiveDataExistsPositive() throws Exception {
149         new JavaTestKit(getSystem()) {{
150             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
151             final Props props =
152                 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
153             final ActorRef subject = getSystem().actorOf(props, "testDataExistsPositive");
154
155             new Within(duration("1 seconds")) {
156                 @Override
157                 protected void run() {
158
159                     subject.tell(
160                         new DataExists(YangInstanceIdentifier.builder().build()).toSerializable(),
161                         getRef());
162
163                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
164                         // do not put code outside this method, will run afterwards
165                         @Override
166                         protected String match(Object in) {
167                             if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
168                                 if (DataExistsReply.fromSerializable(in)
169                                     .exists()) {
170                                     return "match";
171                                 }
172                                 return null;
173                             } else {
174                                 throw noMatch();
175                             }
176                         }
177                     }.get(); // this extracts the received message
178
179                     assertEquals("match", out);
180
181                     expectNoMsg();
182                 }
183
184
185             };
186         }};
187     }
188
189     @Test
190     public void testOnReceiveDataExistsNegative() throws Exception {
191         new JavaTestKit(getSystem()) {{
192             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER,
193                     Collections.EMPTY_MAP, null));
194             final Props props =
195                 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
196             final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative");
197
198             new Within(duration("1 seconds")) {
199                 @Override
200                 protected void run() {
201
202                     subject.tell(
203                         new DataExists(TestModel.TEST_PATH).toSerializable(),
204                         getRef());
205
206                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
207                         // do not put code outside this method, will run afterwards
208                         @Override
209                         protected String match(Object in) {
210                             if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
211                                 if (!DataExistsReply.fromSerializable(in)
212                                     .exists()) {
213                                     return "match";
214                                 }
215                                 return null;
216                             } else {
217                                 throw noMatch();
218                             }
219                         }
220                     }.get(); // this extracts the received message
221
222                     assertEquals("match", out);
223
224                     expectNoMsg();
225                 }
226
227
228             };
229         }};
230     }
231
232     private void assertModification(final ActorRef subject,
233         final Class<? extends Modification> modificationType) {
234         new JavaTestKit(getSystem()) {{
235             new Within(duration("1 seconds")) {
236                 @Override
237                 protected void run() {
238                     subject
239                         .tell(new ShardTransaction.GetCompositedModification(),
240                             getRef());
241
242                     final CompositeModification compositeModification =
243                         new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
244                             // do not put code outside this method, will run afterwards
245                             @Override
246                             protected CompositeModification match(Object in) {
247                                 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
248                                     return ((ShardTransaction.GetCompositeModificationReply) in)
249                                         .getModification();
250                                 } else {
251                                     throw noMatch();
252                                 }
253                             }
254                         }.get(); // this extracts the received message
255
256                     assertTrue(
257                         compositeModification.getModifications().size() == 1);
258                     assertEquals(modificationType,
259                         compositeModification.getModifications().get(0)
260                             .getClass());
261
262                 }
263             };
264         }};
265     }
266
267     @Test
268     public void testOnReceiveWriteData() throws Exception {
269         new JavaTestKit(getSystem()) {{
270             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
271             final Props props =
272                 ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
273             final ActorRef subject =
274                 getSystem().actorOf(props, "testWriteData");
275
276             new Within(duration("1 seconds")) {
277                 @Override
278                 protected void run() {
279
280                     subject.tell(new WriteData(TestModel.TEST_PATH,
281                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
282                         getRef());
283
284                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
285                         // do not put code outside this method, will run afterwards
286                         @Override
287                         protected String match(Object in) {
288                             if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
289                                 return "match";
290                             } else {
291                                 throw noMatch();
292                             }
293                         }
294                     }.get(); // this extracts the received message
295
296                     assertEquals("match", out);
297
298                     assertModification(subject, WriteModification.class);
299                     expectNoMsg();
300                 }
301
302
303             };
304         }};
305     }
306
307     @Test
308     public void testOnReceiveMergeData() throws Exception {
309         new JavaTestKit(getSystem()) {{
310             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
311             final Props props =
312                 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
313             final ActorRef subject =
314                 getSystem().actorOf(props, "testMergeData");
315
316             new Within(duration("1 seconds")) {
317                 @Override
318                 protected void run() {
319
320                     subject.tell(new MergeData(TestModel.TEST_PATH,
321                         ImmutableNodes.containerNode(TestModel.TEST_QNAME), testSchemaContext).toSerializable(),
322                         getRef());
323
324                     final String out = new ExpectMsg<String>(duration("500 milliseconds"), "match hint") {
325                         // do not put code outside this method, will run afterwards
326                         @Override
327                         protected String match(Object in) {
328                             if (in.getClass().equals(MergeDataReply.SERIALIZABLE_CLASS)) {
329                                 return "match";
330                             } else {
331                                 throw noMatch();
332                             }
333                         }
334                     }.get(); // this extracts the received message
335
336                     assertEquals("match", out);
337
338                     assertModification(subject, MergeModification.class);
339
340                     expectNoMsg();
341                 }
342
343
344             };
345         }};
346     }
347
348     @Test
349     public void testOnReceiveDeleteData() throws Exception {
350         new JavaTestKit(getSystem()) {{
351             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
352             final Props props =
353                 ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
354             final ActorRef subject =
355                 getSystem().actorOf(props, "testDeleteData");
356
357             new Within(duration("1 seconds")) {
358                 @Override
359                 protected void run() {
360
361                     subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
362
363                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
364                         // do not put code outside this method, will run afterwards
365                         @Override
366                         protected String match(Object in) {
367                             if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
368                                 return "match";
369                             } else {
370                                 throw noMatch();
371                             }
372                         }
373                     }.get(); // this extracts the received message
374
375                     assertEquals("match", out);
376
377                     assertModification(subject, DeleteModification.class);
378                     expectNoMsg();
379                 }
380
381
382             };
383         }};
384     }
385
386
387     @Test
388     public void testOnReceiveReadyTransaction() throws Exception {
389         new JavaTestKit(getSystem()) {{
390             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
391             final Props props =
392                 ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
393             final ActorRef subject =
394                 getSystem().actorOf(props, "testReadyTransaction");
395
396             new Within(duration("1 seconds")) {
397                 @Override
398                 protected void run() {
399
400                     subject.tell(new ReadyTransaction().toSerializable(), getRef());
401
402                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
403                         // do not put code outside this method, will run afterwards
404                         @Override
405                         protected String match(Object in) {
406                             if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
407                                 return "match";
408                             } else {
409                                 throw noMatch();
410                             }
411                         }
412                     }.get(); // this extracts the received message
413
414                     assertEquals("match", out);
415
416                     expectNoMsg();
417                 }
418
419
420             };
421         }};
422
423     }
424
425     @Test
426     public void testOnReceiveCloseTransaction() throws Exception {
427         new JavaTestKit(getSystem()) {{
428             final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
429             final Props props =
430                 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
431             final ActorRef subject =
432                 getSystem().actorOf(props, "testCloseTransaction");
433
434             watch(subject);
435
436             new Within(duration("2 seconds")) {
437                 @Override
438                 protected void run() {
439
440                     subject.tell(new CloseTransaction().toSerializable(), getRef());
441
442                     final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
443                         // do not put code outside this method, will run afterwards
444                         @Override
445                         protected String match(Object in) {
446                             if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
447                                 return "match";
448                             } else {
449                                 throw noMatch();
450                             }
451                         }
452                     }.get(); // this extracts the received message
453
454                     assertEquals("match", out);
455
456                     final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
457                         // do not put code outside this method, will run afterwards
458                         @Override
459                         protected String match(Object in) {
460                             if (in instanceof Terminated) {
461                                 return "match";
462                             } else {
463                                 throw noMatch();
464                             }
465                         }
466                     }.get(); // this extracts the received message
467
468
469                     expectNoMsg();
470                 }
471
472
473             };
474         }};
475
476     }
477
478
479   @Test
480   public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
481     try {
482
483         final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
484         final Props props =
485             ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
486          final TestActorRef subject = TestActorRef.apply(props,getSystem());
487
488         subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
489         Assert.assertFalse(true);
490
491
492     } catch (Exception cs) {
493       assertEquals(UnknownMessageException.class.getSimpleName(), cs.getClass().getSimpleName());
494       assertTrue(cs.getMessage(), cs.getMessage().startsWith("Unknown message received "));
495     }
496   }
497 }