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.DeleteData;
17 import org.opendaylight.controller.cluster.datastore.messages.DeleteDataReply;
18 import org.opendaylight.controller.cluster.datastore.messages.MergeData;
19 import org.opendaylight.controller.cluster.datastore.messages.MergeDataReply;
20 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
21 import org.opendaylight.controller.cluster.datastore.messages.ReadDataReply;
22 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransaction;
23 import org.opendaylight.controller.cluster.datastore.messages.ReadyTransactionReply;
24 import org.opendaylight.controller.cluster.datastore.messages.WriteData;
25 import org.opendaylight.controller.cluster.datastore.messages.WriteDataReply;
26 import org.opendaylight.controller.cluster.datastore.modification.CompositeModification;
27 import org.opendaylight.controller.cluster.datastore.modification.DeleteModification;
28 import org.opendaylight.controller.cluster.datastore.modification.MergeModification;
29 import org.opendaylight.controller.cluster.datastore.modification.Modification;
30 import org.opendaylight.controller.cluster.datastore.modification.WriteModification;
31 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
32 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
35 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
37 import java.util.Collections;
39 import static org.junit.Assert.assertEquals;
40 import static org.junit.Assert.assertTrue;
42 public class ShardTransactionTest extends AbstractActorTest {
43 private static ListeningExecutorService storeExecutor =
44 MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
46 private static final InMemoryDOMDataStore store =
47 new InMemoryDOMDataStore("OPER", storeExecutor, MoreExecutors.sameThreadExecutor());
49 private static final SchemaContext testSchemaContext = TestModel.createTestContext();
51 private static final ShardIdentifier SHARD_IDENTIFIER =
52 ShardIdentifier.builder().memberName("member-1")
53 .shardName("inventory").type("config").build();
57 store.onGlobalContextUpdated(testSchemaContext);
61 public void testOnReceiveReadData() throws Exception {
62 new JavaTestKit(getSystem()) {{
63 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
65 ShardTransaction.props(store.newReadOnlyTransaction(), shard, testSchemaContext);
66 final ActorRef subject = getSystem().actorOf(props, "testReadData");
68 new Within(duration("1 seconds")) {
70 protected void run() {
73 new ReadData(YangInstanceIdentifier.builder().build()).toSerializable(),
76 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
77 // do not put code outside this method, will run afterwards
79 protected String match(Object in) {
80 if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
81 if (ReadDataReply.fromSerializable(testSchemaContext,YangInstanceIdentifier.builder().build(), in)
82 .getNormalizedNode()!= null) {
90 }.get(); // this extracts the received message
92 assertEquals("match", out);
103 public void testOnReceiveReadDataWhenDataNotFound() throws Exception {
104 new JavaTestKit(getSystem()) {{
105 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
107 ShardTransaction.props( store.newReadOnlyTransaction(), shard, testSchemaContext);
108 final ActorRef subject = getSystem().actorOf(props, "testReadDataWhenDataNotFound");
110 new Within(duration("1 seconds")) {
112 protected void run() {
115 new ReadData(TestModel.TEST_PATH).toSerializable(),
118 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
119 // do not put code outside this method, will run afterwards
121 protected String match(Object in) {
122 if (in.getClass().equals(ReadDataReply.SERIALIZABLE_CLASS)) {
123 if (ReadDataReply.fromSerializable(testSchemaContext,TestModel.TEST_PATH, in)
133 }.get(); // this extracts the received message
135 assertEquals("match", out);
145 private void assertModification(final ActorRef subject,
146 final Class<? extends Modification> modificationType) {
147 new JavaTestKit(getSystem()) {{
148 new Within(duration("1 seconds")) {
150 protected void run() {
152 .tell(new ShardTransaction.GetCompositedModification(),
155 final CompositeModification compositeModification =
156 new ExpectMsg<CompositeModification>(duration("1 seconds"), "match hint") {
157 // do not put code outside this method, will run afterwards
159 protected CompositeModification match(Object in) {
160 if (in instanceof ShardTransaction.GetCompositeModificationReply) {
161 return ((ShardTransaction.GetCompositeModificationReply) in)
167 }.get(); // this extracts the received message
170 compositeModification.getModifications().size() == 1);
171 assertEquals(modificationType,
172 compositeModification.getModifications().get(0)
181 public void testOnReceiveWriteData() throws Exception {
182 new JavaTestKit(getSystem()) {{
183 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
185 ShardTransaction.props(store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
186 final ActorRef subject =
187 getSystem().actorOf(props, "testWriteData");
189 new Within(duration("1 seconds")) {
191 protected void run() {
193 subject.tell(new WriteData(TestModel.TEST_PATH,
194 ImmutableNodes.containerNode(TestModel.TEST_QNAME), TestModel.createTestContext()).toSerializable(),
197 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
198 // do not put code outside this method, will run afterwards
200 protected String match(Object in) {
201 if (in.getClass().equals(WriteDataReply.SERIALIZABLE_CLASS)) {
207 }.get(); // this extracts the received message
209 assertEquals("match", out);
211 assertModification(subject, WriteModification.class);
221 public void testOnReceiveMergeData() throws Exception {
222 new JavaTestKit(getSystem()) {{
223 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
225 ShardTransaction.props(store.newReadWriteTransaction(), shard, testSchemaContext);
226 final ActorRef subject =
227 getSystem().actorOf(props, "testMergeData");
229 new Within(duration("1 seconds")) {
231 protected void run() {
233 subject.tell(new MergeData(TestModel.TEST_PATH,
234 ImmutableNodes.containerNode(TestModel.TEST_QNAME), testSchemaContext).toSerializable(),
237 final String out = new ExpectMsg<String>(duration("500 milliseconds"), "match hint") {
238 // do not put code outside this method, will run afterwards
240 protected String match(Object in) {
241 if (in.getClass().equals(MergeDataReply.SERIALIZABLE_CLASS)) {
247 }.get(); // this extracts the received message
249 assertEquals("match", out);
251 assertModification(subject, MergeModification.class);
262 public void testOnReceiveDeleteData() throws Exception {
263 new JavaTestKit(getSystem()) {{
264 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
266 ShardTransaction.props( store.newWriteOnlyTransaction(), shard, TestModel.createTestContext());
267 final ActorRef subject =
268 getSystem().actorOf(props, "testDeleteData");
270 new Within(duration("1 seconds")) {
272 protected void run() {
274 subject.tell(new DeleteData(TestModel.TEST_PATH).toSerializable(), getRef());
276 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
277 // do not put code outside this method, will run afterwards
279 protected String match(Object in) {
280 if (in.getClass().equals(DeleteDataReply.SERIALIZABLE_CLASS)) {
286 }.get(); // this extracts the received message
288 assertEquals("match", out);
290 assertModification(subject, DeleteModification.class);
301 public void testOnReceiveReadyTransaction() throws Exception {
302 new JavaTestKit(getSystem()) {{
303 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
305 ShardTransaction.props( store.newReadWriteTransaction(), shard, TestModel.createTestContext());
306 final ActorRef subject =
307 getSystem().actorOf(props, "testReadyTransaction");
309 new Within(duration("1 seconds")) {
311 protected void run() {
313 subject.tell(new ReadyTransaction().toSerializable(), getRef());
315 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
316 // do not put code outside this method, will run afterwards
318 protected String match(Object in) {
319 if (in.getClass().equals(ReadyTransactionReply.SERIALIZABLE_CLASS)) {
325 }.get(); // this extracts the received message
327 assertEquals("match", out);
339 public void testOnReceiveCloseTransaction() throws Exception {
340 new JavaTestKit(getSystem()) {{
341 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
343 ShardTransaction.props(store.newReadWriteTransaction(), shard, TestModel.createTestContext());
344 final ActorRef subject =
345 getSystem().actorOf(props, "testCloseTransaction");
349 new Within(duration("2 seconds")) {
351 protected void run() {
353 subject.tell(new CloseTransaction().toSerializable(), getRef());
355 final String out = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
356 // do not put code outside this method, will run afterwards
358 protected String match(Object in) {
359 if (in.getClass().equals(CloseTransactionReply.SERIALIZABLE_CLASS)) {
365 }.get(); // this extracts the received message
367 assertEquals("match", out);
369 final String termination = new ExpectMsg<String>(duration("1 seconds"), "match hint") {
370 // do not put code outside this method, will run afterwards
372 protected String match(Object in) {
373 if (in instanceof Terminated) {
379 }.get(); // this extracts the received message
393 public void testNegativePerformingWriteOperationOnReadTransaction() throws Exception {
396 final ActorRef shard = getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP));
398 ShardTransaction.props(store.newReadOnlyTransaction(), shard, TestModel.createTestContext());
399 final TestActorRef subject = TestActorRef.apply(props,getSystem());
401 subject.receive(new DeleteData(TestModel.TEST_PATH).toSerializable(), ActorRef.noSender());
402 Assert.assertFalse(true);
405 } catch (Exception cs) {
406 assertEquals(UnknownMessageException.class.getSimpleName(), cs.getClass().getSimpleName());
407 assertTrue(cs.getMessage(), cs.getMessage().startsWith("Unknown message received "));