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.mockito.ArgumentCaptor;
19 import org.mockito.Mock;
20 import org.mockito.MockitoAnnotations;
21 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
22 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
24 import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
25 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
27 public class TxChainTest {
30 private DOMDataBroker broker;
32 private DOMTransactionChainListener listener;
34 private DOMDataTreeReadTransaction readOnlyTx;
36 private AbstractWriteTx writeOnlyTx1;
38 private AbstractWriteTx writeOnlyTx2;
40 private AbstractWriteTx writeOnlyTx3;
42 private AutoCloseable registration1;
44 private AutoCloseable registration2;
46 private AutoCloseable registration3;
47 private final ArgumentCaptor<TxListener> captor = ArgumentCaptor.forClass(TxListener.class);
48 private TxChain chain;
51 public void setUp() throws Exception {
52 MockitoAnnotations.initMocks(this);
53 when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTx);
54 when(broker.newWriteOnlyTransaction()).thenReturn(writeOnlyTx1)
55 .thenReturn(writeOnlyTx2).thenReturn(writeOnlyTx3);
56 when(writeOnlyTx1.addListener(any())).thenReturn(registration1);
57 when(writeOnlyTx2.addListener(any())).thenReturn(registration2);
58 when(writeOnlyTx3.addListener(any())).thenReturn(registration3);
59 chain = new TxChain(broker, listener);
63 public void testNewReadOnlyTransactionPrevSubmitted() throws Exception {
64 chain.newWriteOnlyTransaction();
65 verify(writeOnlyTx1).addListener(captor.capture());
66 captor.getValue().onTransactionSubmitted(writeOnlyTx1);
67 chain.newReadOnlyTransaction();
70 @Test(expected = IllegalStateException.class)
71 public void testNewReadOnlyTransactionPrevNotSubmitted() throws Exception {
72 chain.newWriteOnlyTransaction();
73 chain.newReadOnlyTransaction();
77 public void testNewReadWriteTransactionPrevSubmitted() throws Exception {
78 chain.newReadWriteTransaction();
79 verify(writeOnlyTx1).addListener(captor.capture());
80 captor.getValue().onTransactionSubmitted(writeOnlyTx1);
81 chain.newReadWriteTransaction();
84 @Test(expected = IllegalStateException.class)
85 public void testNewReadWriteTransactionPrevNotSubmitted() throws Exception {
86 chain.newReadWriteTransaction();
87 chain.newReadWriteTransaction();
91 public void testNewWriteOnlyTransactionPrevSubmitted() throws Exception {
92 chain.newWriteOnlyTransaction();
93 verify(writeOnlyTx1).addListener(captor.capture());
94 captor.getValue().onTransactionSubmitted(writeOnlyTx1);
95 chain.newWriteOnlyTransaction();
98 @Test(expected = IllegalStateException.class)
99 public void testNewWriteOnlyTransactionPrevNotSubmitted() throws Exception {
100 chain.newWriteOnlyTransaction();
101 chain.newWriteOnlyTransaction();
104 @Test(expected = DOMTransactionChainClosedException.class)
105 public void testCloseAfterFinished() throws Exception {
107 verify(listener).onTransactionChainSuccessful(chain);
108 chain.newReadOnlyTransaction();
112 public void testChainFail() throws Exception {
113 final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
114 verify(writeOnlyTx1).addListener(captor.capture());
116 final TransactionCommitFailedException cause = new TransactionCommitFailedException("fail");
117 captor.getValue().onTransactionFailed(writeOnlyTx1, cause);
118 verify(registration1).close();
119 verify(listener).onTransactionChainFailed(chain, writeOnlyTx1, cause);
123 public void testChainSuccess() throws Exception {
124 final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
126 verify(writeOnlyTx1).addListener(captor.capture());
128 captor.getValue().onTransactionSuccessful(writeOnlyTx1);
129 verify(registration1).close();
130 verify(listener).onTransactionChainSuccessful(chain);
134 public void testCancel() throws Exception {
135 final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
136 verify(writeOnlyTx1).addListener(captor.capture());
138 captor.getValue().onTransactionCancelled(writeOnlyTx1);
139 chain.newWriteOnlyTransaction();
143 public void testMultiplePendingTransactions() throws Exception {
145 final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
146 final ArgumentCaptor<TxListener> captor1 = ArgumentCaptor.forClass(TxListener.class);
147 verify(writeOnlyTx1).addListener(captor1.capture());
150 captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
153 final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
154 final ArgumentCaptor<TxListener> captor2 = ArgumentCaptor.forClass(TxListener.class);
155 verify(writeTx2).addListener(captor2.capture());
158 captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
161 final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
162 final ArgumentCaptor<TxListener> captor3 = ArgumentCaptor.forClass(TxListener.class);
163 verify(writeTx3).addListener(captor3.capture());
166 captor3.getValue().onTransactionCancelled(writeOnlyTx3);
171 //complete first two transactions successfully
172 captor1.getValue().onTransactionSuccessful(writeOnlyTx1);
173 captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
175 verify(registration1).close();
176 verify(registration2).close();
177 verify(registration3).close();
178 verify(listener).onTransactionChainSuccessful(chain);
182 public void testMultiplePendingTransactionsFail() throws Exception {
184 final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
185 final ArgumentCaptor<TxListener> captor1 = ArgumentCaptor.forClass(TxListener.class);
186 verify(writeOnlyTx1).addListener(captor1.capture());
189 captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
192 final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
193 final ArgumentCaptor<TxListener> captor2 = ArgumentCaptor.forClass(TxListener.class);
194 verify(writeTx2).addListener(captor2.capture());
197 captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
200 final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
201 final ArgumentCaptor<TxListener> captor3 = ArgumentCaptor.forClass(TxListener.class);
202 verify(writeTx3).addListener(captor3.capture());
206 //fail 1st transaction
207 final Exception cause1 = new Exception("fail");
208 captor1.getValue().onTransactionFailed(writeOnlyTx1, cause1);
209 //current unsubmitted transaction should be cancelled
210 verify(writeTx3).cancel();
211 captor3.getValue().onTransactionCancelled(writeTx3);
212 //2nd transaction success
213 captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
215 verify(registration1).close();
216 verify(registration2).close();
217 verify(registration3).close();
218 verify(listener).onTransactionChainFailed(chain, writeOnlyTx1, cause1);
219 // 1 transaction failed, onTransactionChainSuccessful must not be called
220 verify(listener, never()).onTransactionChainSuccessful(chain);