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