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.Matchers.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.controller.md.sal.common.api.data.TransactionChainClosedException;
22 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
24 import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
25 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadOnlyTransaction;
27 public class TxChainTest {
30 private DOMDataBroker broker;
32 private TransactionChainListener listener;
34 private DOMDataReadOnlyTransaction 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 = TransactionChainClosedException.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 final ArgumentCaptor<TxListener> captor = ArgumentCaptor.forClass(TxListener.class);
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);