0bf4f48cead2308e62482e7f0dc4c233e31e3646
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / compat / PreBoronTransactionProxyTest.java
1 /*
2  * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore.compat;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Matchers.argThat;
13 import static org.mockito.Matchers.eq;
14 import static org.mockito.Matchers.isA;
15 import static org.mockito.Mockito.doReturn;
16 import static org.mockito.Mockito.verify;
17 import static org.opendaylight.controller.cluster.datastore.TransactionType.READ_WRITE;
18 import akka.actor.ActorRef;
19 import akka.actor.ActorSystem;
20 import akka.actor.Props;
21 import akka.dispatch.Futures;
22 import akka.util.Timeout;
23 import com.google.common.base.Optional;
24 import java.util.concurrent.TimeUnit;
25 import org.junit.Test;
26 import org.mockito.ArgumentMatcher;
27 import org.opendaylight.controller.cluster.datastore.AbstractTransactionProxyTest;
28 import org.opendaylight.controller.cluster.datastore.DataStoreVersions;
29 import org.opendaylight.controller.cluster.datastore.TransactionProxy;
30 import org.opendaylight.controller.cluster.datastore.TransactionType;
31 import org.opendaylight.controller.cluster.datastore.messages.CreateTransaction;
32 import org.opendaylight.controller.cluster.datastore.messages.DataExists;
33 import org.opendaylight.controller.cluster.datastore.messages.ReadData;
34 import org.opendaylight.controller.cluster.datastore.shardstrategy.DefaultShardStrategy;
35 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
36 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
37 import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
40 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
41
42 /**
43  * TransactionProxy unit tests for backwards compatibility with pre-Boron versions.
44  *
45  * @author Thomas Pantelis
46  */
47 @SuppressWarnings("resource")
48 public class PreBoronTransactionProxyTest extends AbstractTransactionProxyTest {
49
50     private CreateTransaction eqLegacyCreateTransaction(final TransactionType type) {
51         ArgumentMatcher<CreateTransaction> matcher = new ArgumentMatcher<CreateTransaction>() {
52             @Override
53             public boolean matches(Object argument) {
54                 if(ShardTransactionMessages.CreateTransaction.class.equals(argument.getClass())) {
55                     CreateTransaction obj = CreateTransaction.fromSerializable(argument);
56                     return obj.getTransactionId().startsWith(memberName) &&
57                             obj.getTransactionType() == type.ordinal();
58                 }
59
60                 return false;
61             }
62         };
63
64         return argThat(matcher);
65     }
66
67     private static ShardTransactionMessages.CreateTransactionReply legacyCreateTransactionReply(ActorRef actorRef,
68             int transactionVersion){
69         return ShardTransactionMessages.CreateTransactionReply.newBuilder()
70             .setTransactionActorPath(actorRef.path().toString())
71             .setTransactionId("txn-1")
72             .setMessageVersion(transactionVersion)
73             .build();
74     }
75
76     private static ReadData eqLegacySerializedReadData(final YangInstanceIdentifier path) {
77         ArgumentMatcher<ReadData> matcher = new ArgumentMatcher<ReadData>() {
78             @Override
79             public boolean matches(Object argument) {
80                 return ShardTransactionMessages.ReadData.class.equals(argument.getClass()) &&
81                        ReadData.fromSerializable(argument).getPath().equals(path);
82             }
83         };
84
85         return argThat(matcher);
86     }
87
88     private static DataExists eqLegacySerializedDataExists() {
89         ArgumentMatcher<DataExists> matcher = new ArgumentMatcher<DataExists>() {
90             @Override
91             public boolean matches(Object argument) {
92                 return ShardTransactionMessages.DataExists.class.equals(argument.getClass()) &&
93                        DataExists.fromSerializable(argument).getPath().equals(TestModel.TEST_PATH);
94             }
95         };
96
97         return argThat(matcher);
98     }
99
100     private ActorRef setupPreBoronActorContextWithInitialCreateTransaction(ActorSystem actorSystem,
101             TransactionType type) {
102         ActorRef shardActorRef = setupActorContextWithoutInitialCreateTransaction(actorSystem,
103                 DefaultShardStrategy.DEFAULT_SHARD, DataStoreVersions.LITHIUM_VERSION);
104
105         ActorRef txActorRef;
106         if(type == TransactionType.WRITE_ONLY) {
107             txActorRef = shardActorRef;
108         } else {
109             txActorRef = actorSystem.actorOf(Props.create(DoNothingActor.class));
110             doReturn(actorSystem.actorSelection(txActorRef.path())).
111                 when(mockActorContext).actorSelection(txActorRef.path().toString());
112
113             doReturn(Futures.successful(legacyCreateTransactionReply(txActorRef, DataStoreVersions.LITHIUM_VERSION)))
114                 .when(mockActorContext).executeOperationAsync(eq(actorSystem.actorSelection(shardActorRef.path())),
115                         eqLegacyCreateTransaction(type), any(Timeout.class));
116         }
117
118         return txActorRef;
119     }
120
121     @Test
122     public void testClose() throws Exception{
123         ActorRef actorRef = setupPreBoronActorContextWithInitialCreateTransaction(getSystem(), READ_WRITE);
124
125         expectBatchedModifications(actorRef, 1);
126
127         TransactionProxy transactionProxy = new TransactionProxy(mockComponentFactory, READ_WRITE);
128
129         transactionProxy.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
130
131         transactionProxy.close();
132
133         verify(mockActorContext).sendOperationAsync(
134                 eq(actorSelection(actorRef)), isA(ShardTransactionMessages.CloseTransaction.class));
135     }
136
137     @Test
138     public void testRead() throws Exception{
139         ActorRef actorRef = setupPreBoronActorContextWithInitialCreateTransaction(getSystem(), READ_WRITE);
140
141         NormalizedNode<?, ?> expectedNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
142         doReturn(readDataReply(expectedNode)).when(mockActorContext).executeOperationAsync(
143                 eq(actorSelection(actorRef)), eqLegacySerializedReadData(TestModel.TEST_PATH), any(Timeout.class));
144
145         TransactionProxy transactionProxy = new TransactionProxy(mockComponentFactory, READ_WRITE);
146
147         Optional<NormalizedNode<?, ?>> readOptional = transactionProxy.read(
148                 TestModel.TEST_PATH).get(5, TimeUnit.SECONDS);
149
150         assertEquals("NormalizedNode isPresent", true, readOptional.isPresent());
151         assertEquals("Response NormalizedNode", expectedNode, readOptional.get());
152     }
153
154     @Test
155     public void testExists() throws Exception{
156         ActorRef actorRef = setupPreBoronActorContextWithInitialCreateTransaction(getSystem(), READ_WRITE);
157
158         doReturn(dataExistsReply(true)).when(mockActorContext).executeOperationAsync(
159                 eq(actorSelection(actorRef)), eqLegacySerializedDataExists(), any(Timeout.class));
160
161         TransactionProxy transactionProxy = new TransactionProxy(mockComponentFactory, READ_WRITE);
162
163         Boolean exists = transactionProxy.exists(TestModel.TEST_PATH).checkedGet(5, TimeUnit.SECONDS);
164         assertEquals("Exists response", true, exists);
165     }
166 }