BUG 1735 Registering a data change listener should be asynchronous
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / ShardTransactionFailureTest.java
1 /*
2  *
3  *  Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
4  *
5  *  This program and the accompanying materials are made available under the
6  *  terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  *  and is available at http://www.eclipse.org/legal/epl-v10.html
8  *
9  */
10
11 package org.opendaylight.controller.cluster.datastore;
12
13 import akka.actor.ActorRef;
14 import akka.actor.Props;
15 import akka.testkit.TestActorRef;
16
17 import com.google.common.util.concurrent.ListeningExecutorService;
18 import com.google.common.util.concurrent.MoreExecutors;
19
20 import org.junit.BeforeClass;
21 import org.junit.Test;
22 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
23 import org.opendaylight.controller.cluster.datastore.jmx.mbeans.shard.ShardStats;
24 import org.opendaylight.controller.cluster.datastore.node.utils.serialization.NormalizedNodeSerializer;
25 import org.opendaylight.controller.md.cluster.datastore.model.TestModel;
26 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
27 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
28 import org.opendaylight.controller.protobuff.messages.common.NormalizedNodeMessages;
29 import org.opendaylight.controller.protobuff.messages.transaction.ShardTransactionMessages;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
31 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33
34 import scala.concurrent.Await;
35 import scala.concurrent.Future;
36 import scala.concurrent.duration.Duration;
37
38 import java.util.Collections;
39 import java.util.concurrent.TimeUnit;
40
41 /**
42  * Covers negative test cases
43  *
44  * @author Basheeruddin Ahmed <syedbahm@cisco.com>
45  */
46 public class ShardTransactionFailureTest extends AbstractActorTest {
47     private static ListeningExecutorService storeExecutor =
48         MoreExecutors.listeningDecorator(MoreExecutors.sameThreadExecutor());
49
50     private static final InMemoryDOMDataStore store =
51         new InMemoryDOMDataStore("OPER", storeExecutor,
52             MoreExecutors.sameThreadExecutor());
53
54     private static final SchemaContext testSchemaContext =
55         TestModel.createTestContext();
56
57     private static final ShardIdentifier SHARD_IDENTIFIER =
58         ShardIdentifier.builder().memberName("member-1")
59             .shardName("inventory").type("operational").build();
60
61     private final DatastoreContext datastoreContext = new DatastoreContext();
62
63     private final ShardStats shardStats = new ShardStats(SHARD_IDENTIFIER.toString(), "DataStore");
64
65     @BeforeClass
66     public static void staticSetup() {
67         store.onGlobalContextUpdated(testSchemaContext);
68     }
69
70     private ActorRef createShard(){
71         return getSystem().actorOf(Shard.props(SHARD_IDENTIFIER, Collections.EMPTY_MAP, new DatastoreContext(), TestModel.createTestContext()));
72     }
73
74     @Test(expected = ReadFailedException.class)
75     public void testNegativeReadWithReadOnlyTransactionClosed()
76         throws Throwable {
77
78         final ActorRef shard = createShard();
79         final Props props = ShardTransaction.props(store.newReadOnlyTransaction(), shard,
80                 testSchemaContext, datastoreContext, shardStats);
81
82         final TestActorRef<ShardTransaction> subject = TestActorRef
83             .create(getSystem(), props,
84                 "testNegativeReadWithReadOnlyTransactionClosed");
85
86         ShardTransactionMessages.ReadData readData =
87             ShardTransactionMessages.ReadData.newBuilder()
88                 .setInstanceIdentifierPathArguments(
89                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
90                         .build()
91                 ).build();
92         Future<Object> future =
93             akka.pattern.Patterns.ask(subject, readData, 3000);
94         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
95
96         subject.underlyingActor().getDOMStoreTransaction().close();
97
98         future = akka.pattern.Patterns.ask(subject, readData, 3000);
99         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
100     }
101
102
103     @Test(expected = ReadFailedException.class)
104     public void testNegativeReadWithReadWriteTransactionClosed()
105         throws Throwable {
106
107         final ActorRef shard = createShard();
108         final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
109                 testSchemaContext, datastoreContext, shardStats);
110
111         final TestActorRef<ShardTransaction> subject = TestActorRef
112             .create(getSystem(), props,
113                 "testNegativeReadWithReadWriteTransactionClosed");
114
115         ShardTransactionMessages.ReadData readData =
116             ShardTransactionMessages.ReadData.newBuilder()
117                 .setInstanceIdentifierPathArguments(
118                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
119                         .build()
120                 ).build();
121
122         Future<Object> future =
123             akka.pattern.Patterns.ask(subject, readData, 3000);
124         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
125
126         subject.underlyingActor().getDOMStoreTransaction().close();
127
128         future = akka.pattern.Patterns.ask(subject, readData, 3000);
129         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
130     }
131
132     @Test(expected = ReadFailedException.class)
133     public void testNegativeExistsWithReadWriteTransactionClosed()
134         throws Throwable {
135
136         final ActorRef shard = createShard();
137         final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
138                 testSchemaContext, datastoreContext, shardStats);
139
140         final TestActorRef<ShardTransaction> subject = TestActorRef
141             .create(getSystem(), props,
142                 "testNegativeExistsWithReadWriteTransactionClosed");
143
144         ShardTransactionMessages.DataExists dataExists =
145             ShardTransactionMessages.DataExists.newBuilder()
146                 .setInstanceIdentifierPathArguments(
147                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
148                         .build()
149                 ).build();
150
151         Future<Object> future =
152             akka.pattern.Patterns.ask(subject, dataExists, 3000);
153         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
154
155         subject.underlyingActor().getDOMStoreTransaction().close();
156
157         future = akka.pattern.Patterns.ask(subject, dataExists, 3000);
158         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
159     }
160
161     @Test(expected = IllegalStateException.class)
162     public void testNegativeWriteWithTransactionReady() throws Exception {
163
164
165         final ActorRef shard = createShard();
166         final Props props = ShardTransaction.props(store.newWriteOnlyTransaction(), shard,
167                 testSchemaContext, datastoreContext, shardStats);
168
169         final TestActorRef<ShardTransaction> subject = TestActorRef
170             .create(getSystem(), props,
171                 "testNegativeWriteWithTransactionReady");
172
173         ShardTransactionMessages.ReadyTransaction readyTransaction =
174             ShardTransactionMessages.ReadyTransaction.newBuilder().build();
175
176         Future<Object> future =
177             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
178         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
179
180         ShardTransactionMessages.WriteData writeData =
181             ShardTransactionMessages.WriteData.newBuilder()
182                 .setInstanceIdentifierPathArguments(
183                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
184                         .build()).setNormalizedNode(
185                 buildNormalizedNode()
186
187             ).build();
188
189         future = akka.pattern.Patterns.ask(subject, writeData, 3000);
190         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
191     }
192
193     @Test(expected = IllegalStateException.class)
194     public void testNegativeReadWriteWithTransactionReady() throws Exception {
195
196
197         final ActorRef shard = createShard();
198         final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
199                 testSchemaContext, datastoreContext, shardStats);
200
201         final TestActorRef<ShardTransaction> subject = TestActorRef
202             .create(getSystem(), props,
203                 "testNegativeReadWriteWithTransactionReady");
204
205         ShardTransactionMessages.ReadyTransaction readyTransaction =
206             ShardTransactionMessages.ReadyTransaction.newBuilder().build();
207
208         Future<Object> future =
209             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
210         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
211
212         ShardTransactionMessages.WriteData writeData =
213             ShardTransactionMessages.WriteData.newBuilder()
214                 .setInstanceIdentifierPathArguments(
215                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
216                         .build()
217                 )
218                 .setNormalizedNode(buildNormalizedNode())
219                 .build();
220
221         future = akka.pattern.Patterns.ask(subject, writeData, 3000);
222         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
223     }
224
225     private NormalizedNodeMessages.Node buildNormalizedNode() {
226         return NormalizedNodeSerializer
227             .serialize(Builders.containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME)).build());
228     }
229
230     @Test(expected = IllegalStateException.class)
231     public void testNegativeMergeTransactionReady() throws Exception {
232
233
234         final ActorRef shard = createShard();
235         final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
236                 testSchemaContext, datastoreContext, shardStats);
237
238         final TestActorRef<ShardTransaction> subject = TestActorRef
239             .create(getSystem(), props, "testNegativeMergeTransactionReady");
240
241         ShardTransactionMessages.ReadyTransaction readyTransaction =
242             ShardTransactionMessages.ReadyTransaction.newBuilder().build();
243
244         Future<Object> future =
245             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
246         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
247
248         ShardTransactionMessages.MergeData mergeData =
249             ShardTransactionMessages.MergeData.newBuilder()
250                 .setInstanceIdentifierPathArguments(
251                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
252                         .build()).setNormalizedNode(
253                 buildNormalizedNode()
254
255             ).build();
256
257         future = akka.pattern.Patterns.ask(subject, mergeData, 3000);
258         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
259     }
260
261
262     @Test(expected = IllegalStateException.class)
263     public void testNegativeDeleteDataWhenTransactionReady() throws Exception {
264
265
266         final ActorRef shard = createShard();
267         final Props props = ShardTransaction.props(store.newReadWriteTransaction(), shard,
268                 testSchemaContext, datastoreContext, shardStats);
269
270         final TestActorRef<ShardTransaction> subject = TestActorRef
271             .create(getSystem(), props,
272                 "testNegativeDeleteDataWhenTransactionReady");
273
274         ShardTransactionMessages.ReadyTransaction readyTransaction =
275             ShardTransactionMessages.ReadyTransaction.newBuilder().build();
276
277         Future<Object> future =
278             akka.pattern.Patterns.ask(subject, readyTransaction, 3000);
279         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
280
281         ShardTransactionMessages.DeleteData deleteData =
282             ShardTransactionMessages.DeleteData.newBuilder()
283                 .setInstanceIdentifierPathArguments(
284                     NormalizedNodeMessages.InstanceIdentifier.newBuilder()
285                         .build()).build();
286
287         future = akka.pattern.Patterns.ask(subject, deleteData, 3000);
288         Await.result(future, Duration.create(3, TimeUnit.SECONDS));
289     }
290 }