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));
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));
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));
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, Collections.EMPTY_MAP));
194 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
195 final ActorRef subject = getSystem().actorOf(props, "testDataExistsNegative");
197 new Within(duration("1 seconds")) {
199 protected void run() {
202 new DataExists(TestModel.TEST_PATH).toSerializable(),
205 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
206 // do not put code outside this method, will run afterwards
208 protected String match(Object in) {
209 if (in.getClass().equals(DataExistsReply.SERIALIZABLE_CLASS)) {
210 if (!DataExistsReply.fromSerializable(in)
219 }.get(); // this extracts the received message
221 assertEquals("match", out);
231 private void assertModification(final ActorRef subject,
232 final Class<? extends Modification> modificationType) {
233 new JavaTestKit(getSystem()) {{
234 new Within(duration("1 seconds")) {
236 protected void run() {
238 .tell(new ShardTransaction.GetCompositedModification(),
241 final CompositeModification compositeModification =
242 new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
243 // do not put code outside this method, will run afterwards
245 protected CompositeModification match(Object in) {
246 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
247 return ((ShardTransaction.GetCompositeModificationReply) in)
253 }.get(); // this extracts the received message
256 compositeModification.getModifications().size() == 1);
257 assertEquals(modificationType,
258 compositeModification.getModifications().get(0)
267 public void testOnReceiveWriteData() throws Exception {
268 new JavaTestKit(getSystem()) {{
269 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
271 ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
272 final ActorRef subject =
273 getSystem().actorOf(props, "testWriteData");
275 new Within(duration("1 seconds")) {
277 protected void run() {
279 subject.tell(new WriteData(TestModel.TEST_PATH,
280 ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
283 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
284 // do not put code outside this method, will run afterwards
286 protected String match(Object in) {
287 if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
293 }.get(); // this extracts the received message
295 assertEquals("match", out);
297 assertModification(subject, WriteModification.class);
307 public void testOnReceiveMergeData() throws Exception {
308 new JavaTestKit(getSystem()) {{
309 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
311 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
312 final ActorRef subject =
313 getSystem().actorOf(props, "testMergeData");
315 new Within(duration("1 seconds")) {
317 protected void run() {
319 subject.tell(new MergeData(TestModel.TEST_PATH,
320 ImmutableNodes.containerNode(TestModel.TEST_QNAME), testSchemaContext).toSerializable(),
323 final String out = new ExpectMsg<String>(duration("500 milliseconds"), "match hint") {
324 // do not put code outside this method, will run afterwards
326 protected String match(Object in) {
327 if (in.getClass().equals(MergeDataReply.SERIALIZABLE_CLASS)) {
333 }.get(); // this extracts the received message
335 assertEquals("match", out);
337 assertModification(subject, MergeModification.class);
348 public void testOnReceiveDeleteData() throws Exception {
349 new JavaTestKit(getSystem()) {{
350 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
352 ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
353 final ActorRef subject =
354 getSystem().actorOf(props, "testDeleteData");
356 new Within(duration("1 seconds")) {
358 protected void run() {
360 subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
362 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
363 // do not put code outside this method, will run afterwards
365 protected String match(Object in) {
366 if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
372 }.get(); // this extracts the received message
374 assertEquals("match", out);
376 assertModification(subject, DeleteModification.class);
387 public void testOnReceiveReadyTransaction() throws Exception {
388 new JavaTestKit(getSystem()) {{
389 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
391 ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
392 final ActorRef subject =
393 getSystem().actorOf(props, "testReadyTransaction");
395 new Within(duration("1 seconds")) {
397 protected void run() {
399 subject.tell(new ReadyTransaction().toSerializable(), getRef());
401 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
402 // do not put code outside this method, will run afterwards
404 protected String match(Object in) {
405 if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
411 }.get(); // this extracts the received message
413 assertEquals("match", out);
425 public void testOnReceiveCloseTransaction() throws Exception {
426 new JavaTestKit(getSystem()) {{
427 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
429 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
430 final ActorRef subject =
431 getSystem().actorOf(props, "testCloseTransaction");
435 new Within(duration("2 seconds")) {
437 protected void run() {
439 subject.tell(new CloseTransaction().toSerializable(), getRef());
441 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
442 // do not put code outside this method, will run afterwards
444 protected String match(Object in) {
445 if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
451 }.get(); // this extracts the received message
453 assertEquals("match", out);
455 final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
456 // do not put code outside this method, will run afterwards
458 protected String match(Object in) {
459 if (in instanceof Terminated) {
465 }.get(); // this extracts the received message
479 public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
482 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
484 ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
485 final TestActorRef subject = TestActorRef.apply(props,getSystem());
487 subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
488 Assert.assertFalse(true);
491 } catch (Exception cs) {
492 assertEquals(UnknownMessageException.class.getSimpleName(), cs.getClass().getSimpleName());
493 assertTrue(cs.getMessage(), cs.getMessage().startsWith("Unknown message received "));