2 * Copyright (c) 2016 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.netconf.sal.connect.netconf.sal.tx;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.Mockito.never;
13 import static org.mockito.Mockito.verify;
14 import static org.mockito.Mockito.when;
16 import org.junit.Before;
17 import org.junit.Test;
18 import org.junit.runner.RunWith;
19 import org.mockito.ArgumentCaptor;
20 import org.mockito.Mock;
21 import org.mockito.junit.MockitoJUnitRunner;
22 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
23 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
25 import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
26 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
28 @RunWith(MockitoJUnitRunner.StrictStubs.class)
29 public class TxChainTest {
32 private DOMDataBroker broker;
34 private DOMTransactionChainListener listener;
36 private DOMDataTreeReadTransaction readOnlyTx;
38 private AbstractWriteTx writeOnlyTx1;
40 private AbstractWriteTx writeOnlyTx2;
42 private AbstractWriteTx writeOnlyTx3;
44 private AutoCloseable registration1;
46 private AutoCloseable registration2;
48 private AutoCloseable registration3;
49 private final ArgumentCaptor<TxListener> captor = ArgumentCaptor.forClass(TxListener.class);
50 private TxChain chain;
53 public void setUp() throws Exception {
54 when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTx);
55 when(broker.newWriteOnlyTransaction()).thenReturn(writeOnlyTx1)
56 .thenReturn(writeOnlyTx2).thenReturn(writeOnlyTx3);
57 when(writeOnlyTx1.addListener(any())).thenReturn(registration1);
58 when(writeOnlyTx2.addListener(any())).thenReturn(registration2);
59 when(writeOnlyTx3.addListener(any())).thenReturn(registration3);
60 chain = new TxChain(broker, listener);
64 public void testNewReadOnlyTransactionPrevSubmitted() throws Exception {
65 chain.newWriteOnlyTransaction();
66 verify(writeOnlyTx1).addListener(captor.capture());
67 captor.getValue().onTransactionSubmitted(writeOnlyTx1);
68 chain.newReadOnlyTransaction();
71 @Test(expected = IllegalStateException.class)
72 public void testNewReadOnlyTransactionPrevNotSubmitted() throws Exception {
73 chain.newWriteOnlyTransaction();
74 chain.newReadOnlyTransaction();
78 public void testNewReadWriteTransactionPrevSubmitted() throws Exception {
79 chain.newReadWriteTransaction();
80 verify(writeOnlyTx1).addListener(captor.capture());
81 captor.getValue().onTransactionSubmitted(writeOnlyTx1);
82 chain.newReadWriteTransaction();
85 @Test(expected = IllegalStateException.class)
86 public void testNewReadWriteTransactionPrevNotSubmitted() throws Exception {
87 chain.newReadWriteTransaction();
88 chain.newReadWriteTransaction();
92 public void testNewWriteOnlyTransactionPrevSubmitted() throws Exception {
93 chain.newWriteOnlyTransaction();
94 verify(writeOnlyTx1).addListener(captor.capture());
95 captor.getValue().onTransactionSubmitted(writeOnlyTx1);
96 chain.newWriteOnlyTransaction();
99 @Test(expected = IllegalStateException.class)
100 public void testNewWriteOnlyTransactionPrevNotSubmitted() throws Exception {
101 chain.newWriteOnlyTransaction();
102 chain.newWriteOnlyTransaction();
105 @Test(expected = DOMTransactionChainClosedException.class)
106 public void testCloseAfterFinished() throws Exception {
108 verify(listener).onTransactionChainSuccessful(chain);
109 chain.newReadOnlyTransaction();
113 public void testChainFail() throws Exception {
114 final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
115 verify(writeOnlyTx1).addListener(captor.capture());
117 final TransactionCommitFailedException cause = new TransactionCommitFailedException("fail");
118 captor.getValue().onTransactionFailed(writeOnlyTx1, cause);
119 verify(registration1).close();
120 verify(listener).onTransactionChainFailed(chain, writeOnlyTx1, cause);
124 public void testChainSuccess() throws Exception {
125 final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
127 verify(writeOnlyTx1).addListener(captor.capture());
129 captor.getValue().onTransactionSuccessful(writeOnlyTx1);
130 verify(registration1).close();
131 verify(listener).onTransactionChainSuccessful(chain);
135 public void testCancel() throws Exception {
136 final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
137 verify(writeOnlyTx1).addListener(captor.capture());
139 captor.getValue().onTransactionCancelled(writeOnlyTx1);
140 chain.newWriteOnlyTransaction();
144 public void testMultiplePendingTransactions() throws Exception {
146 final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
147 final ArgumentCaptor<TxListener> captor1 = ArgumentCaptor.forClass(TxListener.class);
148 verify(writeOnlyTx1).addListener(captor1.capture());
151 captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
154 final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
155 final ArgumentCaptor<TxListener> captor2 = ArgumentCaptor.forClass(TxListener.class);
156 verify(writeTx2).addListener(captor2.capture());
159 captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
162 final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
163 final ArgumentCaptor<TxListener> captor3 = ArgumentCaptor.forClass(TxListener.class);
164 verify(writeTx3).addListener(captor3.capture());
167 captor3.getValue().onTransactionCancelled(writeOnlyTx3);
172 //complete first two transactions successfully
173 captor1.getValue().onTransactionSuccessful(writeOnlyTx1);
174 captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
176 verify(registration1).close();
177 verify(registration2).close();
178 verify(registration3).close();
179 verify(listener).onTransactionChainSuccessful(chain);
183 public void testMultiplePendingTransactionsFail() throws Exception {
185 final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
186 final ArgumentCaptor<TxListener> captor1 = ArgumentCaptor.forClass(TxListener.class);
187 verify(writeOnlyTx1).addListener(captor1.capture());
190 captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
193 final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
194 final ArgumentCaptor<TxListener> captor2 = ArgumentCaptor.forClass(TxListener.class);
195 verify(writeTx2).addListener(captor2.capture());
198 captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
201 final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
202 final ArgumentCaptor<TxListener> captor3 = ArgumentCaptor.forClass(TxListener.class);
203 verify(writeTx3).addListener(captor3.capture());
207 //fail 1st transaction
208 final Exception cause1 = new Exception("fail");
209 captor1.getValue().onTransactionFailed(writeOnlyTx1, cause1);
210 //current unsubmitted transaction should be cancelled
211 verify(writeTx3).cancel();
212 captor3.getValue().onTransactionCancelled(writeTx3);
213 //2nd transaction success
214 captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
216 verify(registration1).close();
217 verify(registration2).close();
218 verify(registration3).close();
219 verify(listener).onTransactionChainFailed(chain, writeOnlyTx1, cause1);
220 // 1 transaction failed, onTransactionChainSuccessful must not be called
221 verify(listener, never()).onTransactionChainSuccessful(chain);