2 * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.controller.md.sal.dom.broker.impl;
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.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
15 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.OPERATIONAL;
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.TimeoutException;
30 import java.util.concurrent.atomic.AtomicReference;
31 import org.junit.After;
32 import org.junit.Before;
33 import org.junit.Test;
34 import org.mockito.Mockito;
35 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
36 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitDeadlockException;
37 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
38 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
39 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
40 import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
41 import org.opendaylight.controller.md.sal.dom.store.impl.InMemoryDOMDataStore;
42 import org.opendaylight.controller.md.sal.dom.store.impl.TestModel;
43 import org.opendaylight.controller.sal.core.spi.data.DOMStore;
44 import org.opendaylight.yangtools.util.concurrent.DeadlockDetectingListeningExecutorService;
45 import org.opendaylight.yangtools.util.concurrent.SpecialExecutors;
46 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
47 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
48 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
51 public class DOMBrokerTest {
53 private SchemaContext schemaContext;
54 private AbstractDOMDataBroker domBroker;
55 private ListeningExecutorService executor;
56 private ExecutorService futureExecutor;
57 private CommitExecutorService commitExecutor;
60 public void setupStore() {
62 InMemoryDOMDataStore operStore = new InMemoryDOMDataStore("OPER", MoreExecutors.newDirectExecutorService());
63 InMemoryDOMDataStore configStore = new InMemoryDOMDataStore("CFG", MoreExecutors.newDirectExecutorService());
64 schemaContext = TestModel.createTestContext();
66 operStore.onGlobalContextUpdated(schemaContext);
67 configStore.onGlobalContextUpdated(schemaContext);
69 final ImmutableMap<LogicalDatastoreType, DOMStore> stores =
70 ImmutableMap.<LogicalDatastoreType, DOMStore>builder() //
71 .put(CONFIGURATION, configStore) //
72 .put(OPERATIONAL, operStore) //
75 commitExecutor = new CommitExecutorService(Executors.newSingleThreadExecutor());
76 futureExecutor = SpecialExecutors.newBlockingBoundedCachedThreadPool(1, 5, "FCB", DOMBrokerTest.class);
77 executor = new DeadlockDetectingListeningExecutorService(commitExecutor,
78 TransactionCommitDeadlockException
79 .DEADLOCK_EXCEPTION_SUPPLIER,
81 domBroker = new SerializedDOMDataBroker(stores, executor);
85 public void tearDown() {
86 if (executor != null) {
87 executor.shutdownNow();
90 if (futureExecutor != null) {
91 futureExecutor.shutdownNow();
95 @Test(timeout = 10000)
96 public void testTransactionIsolation() throws InterruptedException, ExecutionException {
98 assertNotNull(domBroker);
100 DOMDataReadTransaction readTx = domBroker.newReadOnlyTransaction();
101 assertNotNull(readTx);
103 DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
104 assertNotNull(writeTx);
107 * Writes /test in writeTx
110 writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
113 * Reads /test from writeTx Read should return container.
116 ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx
117 .read(OPERATIONAL, TestModel.TEST_PATH);
118 assertTrue(writeTxContainer.get().isPresent());
121 * Reads /test from readTx Read should return Absent.
124 ListenableFuture<Optional<NormalizedNode<?, ?>>> readTxContainer = readTx
125 .read(OPERATIONAL, TestModel.TEST_PATH);
126 assertFalse(readTxContainer.get().isPresent());
129 @Test(timeout = 10000)
130 public void testTransactionCommit() throws InterruptedException, ExecutionException, TimeoutException {
132 DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
133 assertNotNull(writeTx);
136 * Writes /test in writeTx
139 writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
142 * Reads /test from writeTx Read should return container.
145 ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx
146 .read(OPERATIONAL, TestModel.TEST_PATH);
147 assertTrue(writeTxContainer.get().isPresent());
149 writeTx.commit().get(5, TimeUnit.SECONDS);
151 Optional<NormalizedNode<?, ?>> afterCommitRead = domBroker.newReadOnlyTransaction()
152 .read(OPERATIONAL, TestModel.TEST_PATH).get();
153 assertTrue(afterCommitRead.isPresent());
156 @Test(timeout = 10000)
158 public void testTransactionSubmit() throws InterruptedException, ExecutionException, TimeoutException {
160 DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
161 assertNotNull(writeTx);
164 * Writes /test in writeTx
167 writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
170 * Reads /test from writeTx Read should return container.
173 ListenableFuture<Optional<NormalizedNode<?, ?>>> writeTxContainer = writeTx
174 .read(OPERATIONAL, TestModel.TEST_PATH);
175 assertTrue(writeTxContainer.get().isPresent());
177 writeTx.submit().get(5, TimeUnit.SECONDS);
179 Optional<NormalizedNode<?, ?>> afterCommitRead = domBroker.newReadOnlyTransaction()
180 .read(OPERATIONAL, TestModel.TEST_PATH).get();
181 assertTrue(afterCommitRead.isPresent());
184 @Test(expected = TransactionCommitFailedException.class)
185 @SuppressWarnings({"checkstyle:IllegalThrows", "checkstyle:AvoidHidingCauseException"})
186 public void testRejectedCommit() throws Throwable {
188 commitExecutor.delegate = Mockito.mock(ExecutorService.class);
189 Mockito.doThrow(new RejectedExecutionException("mock")).when(commitExecutor.delegate)
190 .execute(Mockito.any(Runnable.class));
191 Mockito.doNothing().when(commitExecutor.delegate).shutdown();
192 Mockito.doReturn(Collections.emptyList()).when(commitExecutor.delegate).shutdownNow();
193 Mockito.doReturn("").when(commitExecutor.delegate).toString();
194 Mockito.doReturn(true).when(commitExecutor.delegate)
195 .awaitTermination(Mockito.anyLong(), Mockito.any(TimeUnit.class));
197 DOMDataReadWriteTransaction writeTx = domBroker.newReadWriteTransaction();
198 writeTx.put(OPERATIONAL, TestModel.TEST_PATH, ImmutableNodes.containerNode(TestModel.TEST_QNAME));
201 writeTx.commit().get(5, TimeUnit.SECONDS);
202 } catch (ExecutionException e) {
207 @SuppressWarnings("checkstyle:IllegalCatch")
208 AtomicReference<Throwable> submitTxAsync(final DOMDataWriteTransaction writeTx) {
209 final AtomicReference<Throwable> caughtEx = new AtomicReference<>();
213 } catch (Throwable e) {
222 static class CommitExecutorService extends ForwardingExecutorService {
224 ExecutorService delegate;
226 CommitExecutorService(final ExecutorService delegate) {
227 this.delegate = delegate;
231 protected ExecutorService delegate() {