Move netconf-console to apps/
[netconf.git] / plugins / sal-netconf-connector / src / test / java / org / opendaylight / netconf / sal / connect / netconf / sal / tx / TxChainTest.java
1 /*
2  * Copyright (c) 2016 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
9 package org.opendaylight.netconf.sal.connect.netconf.sal.tx;
10
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;
15
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;
27
28 @RunWith(MockitoJUnitRunner.StrictStubs.class)
29 public class TxChainTest {
30
31     @Mock
32     private DOMDataBroker broker;
33     @Mock
34     private DOMTransactionChainListener listener;
35     @Mock
36     private DOMDataTreeReadTransaction readOnlyTx;
37     @Mock
38     private AbstractWriteTx writeOnlyTx1;
39     @Mock
40     private AbstractWriteTx writeOnlyTx2;
41     @Mock
42     private AbstractWriteTx writeOnlyTx3;
43     @Mock
44     private AutoCloseable registration1;
45     @Mock
46     private AutoCloseable registration2;
47     @Mock
48     private AutoCloseable registration3;
49     private final ArgumentCaptor<TxListener> captor = ArgumentCaptor.forClass(TxListener.class);
50     private TxChain chain;
51
52     @Before
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);
61     }
62
63     @Test()
64     public void testNewReadOnlyTransactionPrevSubmitted() throws Exception {
65         chain.newWriteOnlyTransaction();
66         verify(writeOnlyTx1).addListener(captor.capture());
67         captor.getValue().onTransactionSubmitted(writeOnlyTx1);
68         chain.newReadOnlyTransaction();
69     }
70
71     @Test(expected = IllegalStateException.class)
72     public void testNewReadOnlyTransactionPrevNotSubmitted() throws Exception {
73         chain.newWriteOnlyTransaction();
74         chain.newReadOnlyTransaction();
75     }
76
77     @Test
78     public void testNewReadWriteTransactionPrevSubmitted() throws Exception {
79         chain.newReadWriteTransaction();
80         verify(writeOnlyTx1).addListener(captor.capture());
81         captor.getValue().onTransactionSubmitted(writeOnlyTx1);
82         chain.newReadWriteTransaction();
83     }
84
85     @Test(expected = IllegalStateException.class)
86     public void testNewReadWriteTransactionPrevNotSubmitted() throws Exception {
87         chain.newReadWriteTransaction();
88         chain.newReadWriteTransaction();
89     }
90
91     @Test
92     public void testNewWriteOnlyTransactionPrevSubmitted() throws Exception {
93         chain.newWriteOnlyTransaction();
94         verify(writeOnlyTx1).addListener(captor.capture());
95         captor.getValue().onTransactionSubmitted(writeOnlyTx1);
96         chain.newWriteOnlyTransaction();
97     }
98
99     @Test(expected = IllegalStateException.class)
100     public void testNewWriteOnlyTransactionPrevNotSubmitted() throws Exception {
101         chain.newWriteOnlyTransaction();
102         chain.newWriteOnlyTransaction();
103     }
104
105     @Test(expected = DOMTransactionChainClosedException.class)
106     public void testCloseAfterFinished() throws Exception {
107         chain.close();
108         verify(listener).onTransactionChainSuccessful(chain);
109         chain.newReadOnlyTransaction();
110     }
111
112     @Test
113     public void testChainFail() throws Exception {
114         final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
115         verify(writeOnlyTx1).addListener(captor.capture());
116         writeTx.commit();
117         final TransactionCommitFailedException cause = new TransactionCommitFailedException("fail");
118         captor.getValue().onTransactionFailed(writeOnlyTx1, cause);
119         verify(registration1).close();
120         verify(listener).onTransactionChainFailed(chain, writeOnlyTx1, cause);
121     }
122
123     @Test
124     public void testChainSuccess() throws Exception {
125         final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
126         chain.close();
127         verify(writeOnlyTx1).addListener(captor.capture());
128         writeTx.commit();
129         captor.getValue().onTransactionSuccessful(writeOnlyTx1);
130         verify(registration1).close();
131         verify(listener).onTransactionChainSuccessful(chain);
132     }
133
134     @Test
135     public void testCancel() throws Exception {
136         final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
137         verify(writeOnlyTx1).addListener(captor.capture());
138         writeTx.cancel();
139         captor.getValue().onTransactionCancelled(writeOnlyTx1);
140         chain.newWriteOnlyTransaction();
141     }
142
143     @Test
144     public void testMultiplePendingTransactions() throws Exception {
145         //create 1st tx
146         final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
147         final ArgumentCaptor<TxListener> captor1 = ArgumentCaptor.forClass(TxListener.class);
148         verify(writeOnlyTx1).addListener(captor1.capture());
149         //submit 1st tx
150         writeTx1.commit();
151         captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
152
153         //create 2nd tx
154         final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
155         final ArgumentCaptor<TxListener> captor2 = ArgumentCaptor.forClass(TxListener.class);
156         verify(writeTx2).addListener(captor2.capture());
157         //submit 2nd tx
158         writeTx2.commit();
159         captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
160
161         //create 3rd tx
162         final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
163         final ArgumentCaptor<TxListener> captor3 = ArgumentCaptor.forClass(TxListener.class);
164         verify(writeTx3).addListener(captor3.capture());
165         //cancel 3rd tx
166         writeTx3.cancel();
167         captor3.getValue().onTransactionCancelled(writeOnlyTx3);
168
169         //close chain
170         chain.close();
171
172         //complete first two transactions successfully
173         captor1.getValue().onTransactionSuccessful(writeOnlyTx1);
174         captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
175
176         verify(registration1).close();
177         verify(registration2).close();
178         verify(registration3).close();
179         verify(listener).onTransactionChainSuccessful(chain);
180     }
181
182     @Test
183     public void testMultiplePendingTransactionsFail() throws Exception {
184         //create 1st tx
185         final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
186         final ArgumentCaptor<TxListener> captor1 = ArgumentCaptor.forClass(TxListener.class);
187         verify(writeOnlyTx1).addListener(captor1.capture());
188         //submit 1st tx
189         writeTx1.commit();
190         captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
191
192         //create 2nd tx
193         final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
194         final ArgumentCaptor<TxListener> captor2 = ArgumentCaptor.forClass(TxListener.class);
195         verify(writeTx2).addListener(captor2.capture());
196         //submit 2nd tx
197         writeTx2.commit();
198         captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
199
200         //create 3rd tx
201         final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
202         final ArgumentCaptor<TxListener> captor3 = ArgumentCaptor.forClass(TxListener.class);
203         verify(writeTx3).addListener(captor3.capture());
204
205         chain.close();
206
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);
215
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);
222     }
223 }