1 package org.opendaylight.controller.cluster.datastore;
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;
39 import java.util.Collections;
41 import static org.junit.Assert.assertEquals;
42 import static org.junit.Assert.assertTrue;
44 public class ShardTransactionTest extends AbstractActorTest {
45 private static ListeningExecutorService storeExecutor =
46 MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
48 private static final InMemoryDOMDataStore store =
49 new InMemoryDOMDataStore("OPER", storeExecutor, MoreExecutors.sameThreadExecutor());
51 private static final SchemaContext testSchemaContext = TestModel.createTestContext();
53 private static final ShardIdentifier SHARD_IDENTIFIER =
54 ShardIdentifier.builder().memberName("member-1")
55 .shardName("inventory").type("config").build();
59 store.onGlobalContextUpdated(testSchemaContext);
63 public void testOnReceiveReadData() throws Exception {
64 new JavaTestKit(getSystem()) {{
65 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
67 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
68 final ActorRef subject = getSystem().actorOf(props, "testReadData");
70 new Within(duration("1 seconds")) {
72 protected void run() {
75 new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
78 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
79 // do not put code outside this method, will run afterwards
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) {
92 }.get(); // this extracts the received message
94 assertEquals("match", out);
105 public void testOnReceiveReadDataWhenDataNotFound() throws Exception {
106 new JavaTestKit(getSystem()) {{
107 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
109 ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
110 final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
112 new Within(duration("1 seconds")) {
114 protected void run() {
117 new ReadData(TestModel.TEST_PATH).toSerializable(),
120 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
121 // do not put code outside this method, will run afterwards
123 protected String match(Object in) {
124 if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
125 if (ReadDataReply.fromSerializable(testSchemaContext,TestModel.TEST_PATH, in)
135 }.get(); // this extracts the received message
137 assertEquals("match", out);
148 public void testOnReceiveDataExistsPositive() throws Exception {
149 new JavaTestKit(getSystem()) {{
150 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
152 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
153 final ActorRef subject = getSystem().actorOf(props, "testDataExistsPositive");
155 new Within(duration("1 seconds")) {
157 protected void run() {
160 new DataExists(YangInstanceIdentifier.builder().build()).toSerializable(),
163 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
164 // do not put code outside this method, will run afterwards
166 protected String match(Object in) {
167 if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
168 if (DataExistsReply.fromSerializable(in)
177 }.get(); // this extracts the received message
179 assertEquals("match", out);
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));
195 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
196 final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative");
198 new Within(duration("1 seconds")) {
200 protected void run() {
203 new DataExists(TestModel.TEST_PATH).toSerializable(),
206 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
207 // do not put code outside this method, will run afterwards
209 protected String match(Object in) {
210 if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
211 if (!DataExistsReply.fromSerializable(in)
220 }.get(); // this extracts the received message
222 assertEquals("match", out);
232 private void assertModification(final ActorRef subject,
233 final Class<? extends Modification> modificationType) {
234 new JavaTestKit(getSystem()) {{
235 new Within(duration("1 seconds")) {
237 protected void run() {
239 .tell(new ShardTransaction.GetCompositedModification(),
242 final CompositeModification compositeModification =
243 new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
244 // do not put code outside this method, will run afterwards
246 protected CompositeModification match(Object in) {
247 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
248 return ((ShardTransaction.GetCompositeModificationReply) in)
254 }.get(); // this extracts the received message
257 compositeModification.getModifications().size() == 1);
258 assertEquals(modificationType,
259 compositeModification.getModifications().get(0)
268 public void testOnReceiveWriteData() throws Exception {
269 new JavaTestKit(getSystem()) {{
270 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
272 ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
273 final ActorRef subject =
274 getSystem().actorOf(props, "testWriteData");
276 new Within(duration("1 seconds")) {
278 protected void run() {
280 subject.tell(new WriteData(TestModel.TEST_PATH,
281 ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
284 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
285 // do not put code outside this method, will run afterwards
287 protected String match(Object in) {
288 if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
294 }.get(); // this extracts the received message
296 assertEquals("match", out);
298 assertModification(subject, WriteModification.class);
308 public void testOnReceiveMergeData() throws Exception {
309 new JavaTestKit(getSystem()) {{
310 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
312 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
313 final ActorRef subject =
314 getSystem().actorOf(props, "testMergeData");
316 new Within(duration("1 seconds")) {
318 protected void run() {
320 subject.tell(new MergeData(TestModel.TEST_PATH,
321 ImmutableNodes.containerNode(TestModel.TEST_QNAME), testSchemaContext).toSerializable(),
324 final String out = new ExpectMsg<String>(duration("500 milliseconds"), "match hint") {
325 // do not put code outside this method, will run afterwards
327 protected String match(Object in) {
328 if (in.getClass().equals(MergeDataReply.SERIALIZABLE_CLASS)) {
334 }.get(); // this extracts the received message
336 assertEquals("match", out);
338 assertModification(subject, MergeModification.class);
349 public void testOnReceiveDeleteData() throws Exception {
350 new JavaTestKit(getSystem()) {{
351 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
353 ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
354 final ActorRef subject =
355 getSystem().actorOf(props, "testDeleteData");
357 new Within(duration("1 seconds")) {
359 protected void run() {
361 subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
363 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
364 // do not put code outside this method, will run afterwards
366 protected String match(Object in) {
367 if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
373 }.get(); // this extracts the received message
375 assertEquals("match", out);
377 assertModification(subject, DeleteModification.class);
388 public void testOnReceiveReadyTransaction() throws Exception {
389 new JavaTestKit(getSystem()) {{
390 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
392 ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
393 final ActorRef subject =
394 getSystem().actorOf(props, "testReadyTransaction");
396 new Within(duration("1 seconds")) {
398 protected void run() {
400 subject.tell(new ReadyTransaction().toSerializable(), getRef());
402 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
403 // do not put code outside this method, will run afterwards
405 protected String match(Object in) {
406 if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
412 }.get(); // this extracts the received message
414 assertEquals("match", out);
426 public void testOnReceiveCloseTransaction() throws Exception {
427 new JavaTestKit(getSystem()) {{
428 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
430 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
431 final ActorRef subject =
432 getSystem().actorOf(props, "testCloseTransaction");
436 new Within(duration("2 seconds")) {
438 protected void run() {
440 subject.tell(new CloseTransaction().toSerializable(), getRef());
442 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
443 // do not put code outside this method, will run afterwards
445 protected String match(Object in) {
446 if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
452 }.get(); // this extracts the received message
454 assertEquals("match", out);
456 final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
457 // do not put code outside this method, will run afterwards
459 protected String match(Object in) {
460 if (in instanceof Terminated) {
466 }.get(); // this extracts the received message
480 public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
483 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, null));
485 ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
486 final TestActorRef subject = TestActorRef.apply(props,getSystem());
488 subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
489 Assert.assertFalse(true);
492 } catch (Exception cs) {
493 assertEquals(UnknownMessageException.class.getSimpleName(), cs.getClass().getSimpleName());
494 assertTrue(cs.getMessage(), cs.getMessage().startsWith("Unknown message received "));