Fix odlparent-3.0.0 checkstyle issues
[mdsal.git] / dom / mdsal-dom-inmemory-datastore / src / test / java / org / opendaylight / controller / md / sal / dom / store / impl / InMemoryDataStoreTest.java
1 /*
2  * Copyright (c) 2014 Cisco 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.md.sal.dom.store.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14
15 import com.google.common.base.Optional;
16 import com.google.common.util.concurrent.ListenableFuture;
17 import com.google.common.util.concurrent.MoreExecutors;
18 import java.io.IOException;
19 import java.util.concurrent.ExecutionException;
20 import org.junit.Before;
21 import org.junit.Ignore;
22 import org.junit.Test;
23 import org.mockito.Mockito;
24 import org.opendaylight.mdsal.common.api.ReadFailedException;
25 import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadTransaction;
26 import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadWriteTransaction;
27 import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
28 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionChain;
29 import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
30 import org.opendaylight.mdsal.dom.spi.store.SnapshotBackedTransactions;
31 import org.opendaylight.mdsal.dom.spi.store.SnapshotBackedWriteTransaction.TransactionReadyPrototype;
32 import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStore;
33 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
37 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
38 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeSnapshot;
39 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
40 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
41 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
42 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
43 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
44
45 public class InMemoryDataStoreTest {
46
47     private SchemaContext schemaContext;
48     private InMemoryDOMDataStore domStore;
49
50     @Before
51     public void setupStore() throws IOException, YangSyntaxErrorException, ReactorException {
52         domStore = new InMemoryDOMDataStore("TEST", MoreExecutors.newDirectExecutorService());
53         schemaContext = TestModel.createTestContext();
54         domStore.onGlobalContextUpdated(schemaContext);
55     }
56
57     @Test
58     public void testTransactionIsolation() throws InterruptedException, ExecutionException {
59
60         assertNotNull(domStore);
61
62         DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
63         assertNotNull(readTx);
64
65         DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
66         assertNotNull(writeTx);
67
68         /**
69          * Writes /test in writeTx.
70          */
71         NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
72         writeTx.write(TestModel.TEST_PATH, testNode);
73
74         /**
75          * Reads /test from writeTx Read should return container.
76          */
77         ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
78         assertEquals("read: isPresent", true, writeTxContainer.get().isPresent());
79         assertEquals("read: data", testNode, writeTxContainer.get().get());
80
81         /**
82          * Reads /test from readTx Read should return Absent.
83          */
84         ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx.read(TestModel.TEST_PATH);
85         assertEquals("read: isPresent", false, readTxContainer.get().isPresent());
86     }
87
88     @Test
89     public void testTransactionCommit() throws InterruptedException, ExecutionException {
90
91         DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
92         assertNotNull(writeTx);
93
94         /**
95          * Writes /test in writeTx.
96          */
97         NormalizedNode<?, ?> testNode = ImmutableNodes.containerNode(TestModel.TEST_QNAME);
98         writeTx.write(TestModel.TEST_PATH, testNode);
99
100         /**
101          * Reads /test from writeTx Read should return container.
102          */
103         ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx.read(TestModel.TEST_PATH);
104         assertEquals("read: isPresent", true, writeTxContainer.get().isPresent());
105         assertEquals("read: data", testNode, writeTxContainer.get().get());
106
107         DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
108
109         assertThreePhaseCommit(cohort);
110
111         Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
112                 .get();
113         assertEquals("After commit read: isPresent", true, afterCommitRead.isPresent());
114         assertEquals("After commit read: data", testNode, afterCommitRead.get());
115     }
116
117     @Test
118     public void testDelete() throws Exception {
119
120         DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
121         assertNotNull(writeTx);
122
123         // Write /test and commit
124
125         writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
126
127         assertThreePhaseCommit(writeTx.ready());
128
129         Optional<NormalizedNode<?, ?>> afterCommitRead =
130                 domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH).get();
131         assertEquals("After commit read: isPresent", true, afterCommitRead.isPresent());
132
133         // Delete /test and verify
134
135         writeTx = domStore.newWriteOnlyTransaction();
136
137         writeTx.delete(TestModel.TEST_PATH);
138
139         assertThreePhaseCommit(writeTx.ready());
140
141         afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH).get();
142         assertEquals("After commit read: isPresent", false, afterCommitRead.isPresent());
143     }
144
145     @Test
146     public void testMerge() throws Exception {
147
148         DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
149         assertNotNull(writeTx);
150
151         ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
152                 .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME))
153                 .addChild(ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
154                         .addChild(ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME,
155                                                             TestModel.ID_QNAME, 1)).build()).build();
156
157         writeTx.merge(TestModel.TEST_PATH, containerNode);
158
159         assertThreePhaseCommit(writeTx.ready());
160
161         Optional<NormalizedNode<?, ?>> afterCommitRead =
162                 domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH).get();
163         assertEquals("After commit read: isPresent", true, afterCommitRead.isPresent());
164         assertEquals("After commit read: data", containerNode, afterCommitRead.get());
165
166         // Merge a new list entry node
167
168         writeTx = domStore.newWriteOnlyTransaction();
169         assertNotNull(writeTx);
170
171         containerNode = ImmutableContainerNodeBuilder.create()
172                 .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME))
173                 .addChild(ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
174                         .addChild(ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME,
175                                                             TestModel.ID_QNAME, 1))
176                         .addChild(ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME,
177                                                             TestModel.ID_QNAME, 2)).build()).build();
178
179         writeTx.merge(TestModel.TEST_PATH, containerNode);
180
181         assertThreePhaseCommit(writeTx.ready());
182
183         afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH).get();
184         assertEquals("After commit read: isPresent", true, afterCommitRead.isPresent());
185         assertEquals("After commit read: data", containerNode, afterCommitRead.get());
186     }
187
188
189     @Test
190     public void testExistsForExistingData() throws Exception {
191
192         DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
193         assertNotNull(writeTx);
194
195         ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
196             .withNodeIdentifier(new NodeIdentifier(TestModel.TEST_QNAME))
197             .addChild(ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
198                 .addChild(ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME,
199                     TestModel.ID_QNAME, 1)).build()).build();
200
201         writeTx.merge(TestModel.TEST_PATH, containerNode);
202
203         ListenableFuture<Boolean> exists = writeTx.exists(TestModel.TEST_PATH);
204
205         assertEquals(Boolean.TRUE, exists.get());
206
207         DOMStoreThreePhaseCommitCohort ready = writeTx.ready();
208
209         ready.preCommit().get();
210
211         ready.commit().get();
212
213         DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
214         assertNotNull(readTx);
215
216         exists =
217             readTx.exists(TestModel.TEST_PATH);
218
219         assertEquals(Boolean.TRUE, exists.get());
220     }
221
222     @Test
223     public void testExistsForNonExistingData() throws Exception {
224
225         DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
226         assertNotNull(writeTx);
227
228         ListenableFuture<Boolean> exists = writeTx.exists(TestModel.TEST_PATH);
229
230         assertEquals(Boolean.FALSE, exists.get());
231
232         DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
233         assertNotNull(readTx);
234
235         exists =
236             readTx.exists(TestModel.TEST_PATH);
237
238         assertEquals(Boolean.FALSE, exists.get());
239     }
240
241     @Test(expected = ReadFailedException.class)
242     public void testExistsThrowsReadFailedException() throws Exception {
243
244         DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
245         assertNotNull(readTx);
246
247         readTx.close();
248
249         readTx.exists(TestModel.TEST_PATH).checkedGet();
250     }
251
252
253     @SuppressWarnings("checkstyle:IllegalThrows")
254     @Test(expected = ReadFailedException.class)
255     public void testReadWithReadOnlyTransactionClosed() throws Throwable {
256
257         DOMStoreReadTransaction readTx = domStore.newReadOnlyTransaction();
258         assertNotNull(readTx);
259
260         readTx.close();
261
262         doReadAndThrowEx(readTx);
263     }
264
265     @SuppressWarnings("checkstyle:IllegalThrows")
266     @Test(expected = ReadFailedException.class)
267     public void testReadWithReadOnlyTransactionFailure() throws Throwable {
268
269         DataTreeSnapshot mockSnapshot = Mockito.mock(DataTreeSnapshot.class);
270         Mockito.doThrow(new RuntimeException("mock ex")).when(mockSnapshot)
271         .readNode(Mockito.any(YangInstanceIdentifier.class));
272
273         DOMStoreReadTransaction readTx = SnapshotBackedTransactions.newReadTransaction("1", true, mockSnapshot);
274
275         doReadAndThrowEx(readTx);
276     }
277
278     @SuppressWarnings("checkstyle:IllegalThrows")
279     @Test(expected = ReadFailedException.class)
280     public void testReadWithReadWriteTransactionClosed() throws Throwable {
281
282         DOMStoreReadTransaction readTx = domStore.newReadWriteTransaction();
283         assertNotNull(readTx);
284
285         readTx.close();
286
287         doReadAndThrowEx(readTx);
288     }
289
290     @SuppressWarnings("checkstyle:IllegalThrows")
291     @Test(expected = ReadFailedException.class)
292     public void testReadWithReadWriteTransactionFailure() throws Throwable {
293
294         DataTreeSnapshot mockSnapshot = Mockito.mock(DataTreeSnapshot.class);
295         DataTreeModification mockModification = Mockito.mock(DataTreeModification.class);
296         Mockito.doThrow(new RuntimeException("mock ex")).when(mockModification)
297         .readNode(Mockito.any(YangInstanceIdentifier.class));
298         Mockito.doReturn(mockModification).when(mockSnapshot).newModification();
299         @SuppressWarnings("unchecked")
300         TransactionReadyPrototype<String> mockReady = Mockito.mock(TransactionReadyPrototype.class);
301         DOMStoreReadTransaction readTx = SnapshotBackedTransactions.newReadWriteTransaction(
302                 "1", false, mockSnapshot, mockReady);
303
304         doReadAndThrowEx(readTx);
305     }
306
307     @SuppressWarnings({ "checkstyle:IllegalThrows", "checkstyle:avoidHidingCauseException" })
308     private static void doReadAndThrowEx(final DOMStoreReadTransaction readTx) throws Throwable {
309         try {
310             readTx.read(TestModel.TEST_PATH).get();
311         } catch (ExecutionException e) {
312             throw e.getCause();
313         }
314     }
315
316     @Test(expected = IllegalStateException.class)
317     public void testWriteWithTransactionReady() throws Exception {
318
319         DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
320
321         writeTx.ready();
322
323         // Should throw ex
324         writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
325     }
326
327     @Test(expected = IllegalStateException.class)
328     public void testReadyWithTransactionAlreadyReady() throws Exception {
329
330         DOMStoreWriteTransaction writeTx = domStore.newWriteOnlyTransaction();
331
332         writeTx.ready();
333
334         // Should throw ex
335         writeTx.ready();
336     }
337
338     @Test
339     public void testTransactionAbort() throws InterruptedException, ExecutionException {
340
341         DOMStoreReadWriteTransaction writeTx = domStore.newReadWriteTransaction();
342         assertNotNull(writeTx);
343
344         assertTestContainerWrite(writeTx);
345
346         DOMStoreThreePhaseCommitCohort cohort = writeTx.ready();
347
348         assertTrue(cohort.canCommit().get().booleanValue());
349         cohort.preCommit().get();
350         cohort.abort().get();
351
352         Optional<NormalizedNode<?, ?>> afterCommitRead = domStore.newReadOnlyTransaction().read(TestModel.TEST_PATH)
353                 .get();
354         assertFalse(afterCommitRead.isPresent());
355     }
356
357     @Test
358     public void testTransactionChain() throws InterruptedException, ExecutionException {
359         DOMStoreTransactionChain txChain = domStore.createTransactionChain();
360         assertNotNull(txChain);
361
362         /**
363          * We alocate new read-write transaction and write /test.
364          */
365         DOMStoreReadWriteTransaction firstTx = txChain.newReadWriteTransaction();
366         assertTestContainerWrite(firstTx);
367
368         /**
369          * First transaction is marked as ready, we are able to allocate chained
370          * transactions.
371          */
372         final DOMStoreThreePhaseCommitCohort firstWriteTxCohort = firstTx.ready();
373
374         /**
375          * We alocate chained transaction - read transaction, note first one is
376          * still not commited to datastore.
377          */
378         DOMStoreReadTransaction secondReadTx = txChain.newReadOnlyTransaction();
379
380         /**
381          * We test if we are able to read data from tx, read should not fail
382          * since we are using chained transaction.
383          */
384         assertTestContainerExists(secondReadTx);
385
386         /**
387          * We alocate next transaction, which is still based on first one, but
388          * is read-write.
389          */
390         DOMStoreReadWriteTransaction thirdDeleteTx = txChain.newReadWriteTransaction();
391
392         /**
393          * We test existence of /test in third transaction container should
394          * still be visible from first one (which is still uncommmited).
395          */
396         assertTestContainerExists(thirdDeleteTx);
397
398         /**
399          * We delete node in third transaction.
400          */
401         thirdDeleteTx.delete(TestModel.TEST_PATH);
402
403         /**
404          * third transaction is sealed.
405          */
406         DOMStoreThreePhaseCommitCohort thirdDeleteTxCohort = thirdDeleteTx.ready();
407
408         /**
409          * We commit first transaction.
410          *
411          */
412         assertThreePhaseCommit(firstWriteTxCohort);
413
414         // Alocates store transacion
415         DOMStoreReadTransaction storeReadTx = domStore.newReadOnlyTransaction();
416         /**
417          * We verify transaction is commited to store, container should exists
418          * in datastore.
419          */
420         assertTestContainerExists(storeReadTx);
421         /**
422          * We commit third transaction
423          *
424          */
425         assertThreePhaseCommit(thirdDeleteTxCohort);
426     }
427
428     @Test
429     @Ignore
430     public void testTransactionConflict() throws InterruptedException, ExecutionException {
431         DOMStoreReadWriteTransaction txOne = domStore.newReadWriteTransaction();
432         DOMStoreReadWriteTransaction txTwo = domStore.newReadWriteTransaction();
433         assertTestContainerWrite(txOne);
434         assertTestContainerWrite(txTwo);
435
436         /**
437          * Commits transaction
438          */
439         assertThreePhaseCommit(txOne.ready());
440
441         /**
442          * Asserts that txTwo could not be commited
443          */
444         assertFalse(txTwo.ready().canCommit().get());
445     }
446
447     private static void assertThreePhaseCommit(final DOMStoreThreePhaseCommitCohort cohort)
448             throws InterruptedException, ExecutionException {
449         assertTrue(cohort.canCommit().get().booleanValue());
450         cohort.preCommit().get();
451         cohort.commit().get();
452     }
453
454     private static Optional<NormalizedNode<?, ?>> assertTestContainerWrite(final DOMStoreReadWriteTransaction writeTx)
455             throws InterruptedException, ExecutionException {
456         /**
457          *
458          * Writes /test in writeTx
459          *
460          */
461         writeTx.write(TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
462
463         return assertTestContainerExists(writeTx);
464     }
465
466     /**
467      * Reads /test from readTx Read should return container.
468      */
469     private static Optional<NormalizedNode<?, ?>> assertTestContainerExists(final DOMStoreReadTransaction readTx)
470             throws InterruptedException, ExecutionException {
471
472         ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = readTx.read(TestModel.TEST_PATH);
473         assertTrue(writeTxContainer.get().isPresent());
474         return writeTxContainer.get();
475     }
476
477 }