Bug 5947: Increasing code coverage for mdsal project
[mdsal.git] / dom / mdsal-dom-broker / src / test / java / org / opendaylight / mdsal / dom / broker / test / DOMBrokerTest.java
1 /*
2  * Copyright (c) 2014, 2015 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.mdsal.dom.broker.test;
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 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.CONFIGURATION;
15 import static org.opendaylight.mdsal.common.api.LogicalDatastoreType.OPERATIONAL;
16
17 import com.google.common.base.Optional;
18 import com.google.common.collect.ImmutableMap;
19 import com.google.common.util.concurrent.ForwardingExecutorService;
20 import com.google.common.util.concurrent.ListenableFuture;
21 import com.google.common.util.concurrent.ListeningExecutorService;
22 import com.google.common.util.concurrent.MoreExecutors;
23 import java.util.Collections;
24 import java.util.concurrent.ExecutionException;
25 import java.util.concurrent.ExecutorService;
26 import java.util.concurrent.Executors;
27 import java.util.concurrent.RejectedExecutionException;
28 import java.util.concurrent.TimeUnit;
29 import java.util.concurrent.atomic.AtomicReference;
30 import org.junit.After;
31 import org.junit.Before;
32 import org.junit.Test;
33 import org.mockito.Mockito;
34 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
35 import org.opendaylight.mdsal.common.api.ReadFailedException;
36 import org.opendaylight.mdsal.common.api.TransactionCommitDeadlockException;
37 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
38 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
39 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
40 import org.opendaylight.mdsal.dom.broker.AbstractDOMDataBroker;
41 import org.opendaylight.mdsal.dom.broker.SerializedDOMDataBroker;
42 import org.opendaylight.mdsal.dom.broker.test.util.TestModel;
43 import org.opendaylight.mdsal.dom.spi.store.DOMStore;
44 import org.opendaylight.mdsal.dom.store.inmemory.InMemoryDOMDataStore;
45 import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
46 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
47 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
48 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
49 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
50 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
51 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
52 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
53
54 public class DOMBrokerTest {
55
56     private SchemaContext schemaContext;
57     private AbstractDOMDataBroker domBroker;
58     private ListeningExecutorService executor;
59     private ExecutorService futureExecutor;
60     private CommitExecutorService commitExecutor;
61
62     @Before
63     public void setupStore() throws Exception {
64         InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER",
65                 MoreExecutors.newDirectExecutorService());
66         InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG",
67                 MoreExecutors.newDirectExecutorService());
68         schemaContext = TestModel.createTestContext();
69
70         operStore.onGlobalContextUpdated(schemaContext);
71         configStore.onGlobalContextUpdated(schemaContext);
72
73         ImmutableMap<LogicalDatastoreType, DOMStore> stores = ImmutableMap.<LogicalDatastoreType, DOMStore> builder()
74                 .put(CONFIGURATION, configStore)
75                 .put(OPERATIONAL, operStore)
76                 .build();
77
78         commitExecutor = new CommitExecutorService(Executors.newSingleThreadExecutor());
79         futureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(1, 5, "FCB");
80         executor = new DeadlockDetectingListeningExecutorService(commitExecutor,
81                 TransactionCommitDeadlockException.DEADLOCK_EXCEPTION_SUPPLIER, futureExecutor);
82         domBroker = new SerializedDOMDataBroker(stores, executor);
83     }
84
85     @After
86     public void tearDown() {
87         if( executor != null ) {
88             executor.shutdownNow();
89         }
90
91         if(futureExecutor != null) {
92             futureExecutor.shutdownNow();
93         }
94     }
95
96     @Test(timeout=10000)
97     public void testTransactionIsolation() throws InterruptedException, ExecutionException {
98         assertNotNull(domBroker);
99
100         DOMDataTreeReadTransaction readTx = domBroker.newReadOnlyTransaction();
101         assertNotNull(readTx);
102
103         DOMDataTreeWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
104         assertNotNull(writeTx);
105
106         /**
107          *
108          * Writes /test in writeTx
109          *
110          */
111         writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
112
113         /**
114          *
115          * Reads /test from readTx Read should return Absent.
116          *
117          */
118         ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx
119                 .read(OPERATIONAL, TestModel.TEST_PATH);
120         assertFalse(readTxContainer.get().isPresent());
121     }
122
123     @Test(timeout=10000)
124     public void testTransactionCommit() throws InterruptedException, ExecutionException {
125         DOMDataTreeWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
126         assertNotNull(writeTx);
127         /**
128          *
129          * Writes /test in writeTx
130          *
131          */
132         writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
133
134         writeTx.submit().get();
135
136         Optional<NormalizedNode<?, ?>> afterCommitRead = domBroker.newReadOnlyTransaction()
137                 .read(OPERATIONAL, TestModel.TEST_PATH).get();
138         assertTrue(afterCommitRead.isPresent());
139     }
140
141     @Test(expected=TransactionCommitFailedException.class)
142     public void testRejectedCommit() throws Exception {
143         commitExecutor.delegate = Mockito.mock( ExecutorService.class );
144         Mockito.doThrow( new RejectedExecutionException( "mock" ) )
145             .when( commitExecutor.delegate ).execute( Mockito.any( Runnable.class ) );
146         Mockito.doNothing().when( commitExecutor.delegate ).shutdown();
147         Mockito.doReturn( Collections.emptyList() ).when( commitExecutor.delegate ).shutdownNow();
148         Mockito.doReturn( "" ).when( commitExecutor.delegate ).toString();
149         Mockito.doReturn( true ).when( commitExecutor.delegate )
150             .awaitTermination( Mockito.anyLong(), Mockito.any( TimeUnit.class ) );
151
152         DOMDataTreeWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
153         writeTx.put( OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME) );
154
155         writeTx.submit().checkedGet( 5, TimeUnit.SECONDS );
156     }
157
158     AtomicReference<Throwable> submitTxAsync( final DOMDataTreeWriteTransaction writeTx ) {
159         final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
160         new Thread() {
161             @Override
162             public void run() {
163
164                 try {
165                     writeTx.submit();
166                 } catch( Throwable e ) {
167                     caughtEx.set( e );
168                 }
169             }
170
171         }.start();
172
173         return caughtEx;
174     }
175
176     @Test(expected = ReadFailedException.class)
177     public void basicTests() throws Exception {
178         final DataContainerChild<?, ?> outerList = ImmutableNodes.mapNodeBuilder(TestModel.OUTER_LIST_QNAME)
179                 .withChild(ImmutableNodes.mapEntry(TestModel.OUTER_LIST_QNAME, TestModel.ID_QNAME, 1))
180                 .build();
181         final NormalizedNode<?, ?> testContainer = Builders.containerBuilder()
182                 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TestModel.TEST_QNAME))
183                 .withChild(outerList)
184                 .build();
185
186         DOMDataTreeWriteTransaction writeTx = domBroker.newWriteOnlyTransaction();
187         DOMDataTreeReadTransaction readRx = domBroker.newReadOnlyTransaction();
188         assertNotNull(writeTx);
189         assertNotNull(readRx);
190
191         writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
192         writeTx.submit().get();
193         assertFalse(writeTx.cancel());
194
195         assertEquals(false, domBroker.newReadOnlyTransaction().exists(CONFIGURATION, TestModel.TEST_PATH).get());
196         assertEquals(true, domBroker.newReadOnlyTransaction().exists(OPERATIONAL, TestModel.TEST_PATH).get());
197         assertEquals(false, domBroker.newReadOnlyTransaction().exists(OPERATIONAL, TestModel.TEST2_PATH).get());
198
199         writeTx = domBroker.newWriteOnlyTransaction();
200         writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
201         writeTx.delete(OPERATIONAL, TestModel.TEST_PATH);
202         writeTx.submit().get();
203         assertEquals(false, domBroker.newReadOnlyTransaction().exists(OPERATIONAL, TestModel.TEST_PATH).get());
204         assertTrue(domBroker.newWriteOnlyTransaction().cancel());
205
206         writeTx = domBroker.newWriteOnlyTransaction();
207         writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
208         writeTx.merge(OPERATIONAL, TestModel.TEST_PATH, testContainer);
209         writeTx.submit().get();
210         assertEquals(true, domBroker.newReadOnlyTransaction().exists(OPERATIONAL, TestModel.TEST_PATH).get());
211         assertEquals(true, domBroker.newReadOnlyTransaction().read(OPERATIONAL, TestModel.TEST_PATH).get()
212                  .get().toString().contains(testContainer.toString()));
213
214         readRx.close();
215         //Expected exception after close call
216         readRx.read(OPERATIONAL, TestModel.TEST_PATH).checkedGet();
217     }
218
219     @Test
220     public void closeTest() throws Exception {
221         final String TEST_EXCEPTION = "TestException";
222
223         domBroker.setCloseable(() -> { throw new Exception(TEST_EXCEPTION); });
224         try{
225             domBroker.close();
226         }catch(Exception e){
227             assertTrue(e.getMessage().contains(TEST_EXCEPTION));
228         }
229     }
230
231     static class CommitExecutorService extends ForwardingExecutorService {
232
233         ExecutorService delegate;
234
235         public CommitExecutorService( final ExecutorService delegate ) {
236             this.delegate = delegate;
237         }
238
239         @Override
240         protected ExecutorService delegate() {
241             return delegate;
242         }
243     }
244 }