Bump upstreams
[netconf.git] / plugins / netconf-client-mdsal / src / test / java / org / opendaylight / netconf / client / mdsal / spi / 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 package org.opendaylight.netconf.client.mdsal.spi;
9
10 import static org.junit.Assert.assertThrows;
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 com.google.common.util.concurrent.FutureCallback;
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.junit.runner.RunWith;
20 import org.mockito.ArgumentCaptor;
21 import org.mockito.Captor;
22 import org.mockito.Mock;
23 import org.mockito.junit.MockitoJUnitRunner;
24 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
25 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
27 import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
28 import org.opendaylight.yangtools.concepts.Registration;
29 import org.opendaylight.yangtools.yang.common.Empty;
30
31 @RunWith(MockitoJUnitRunner.StrictStubs.class)
32 public class TxChainTest {
33     @Mock
34     private DOMDataBroker broker;
35     @Mock
36     private FutureCallback<Empty> listener;
37     @Mock
38     private DOMDataTreeReadTransaction readOnlyTx;
39     @Mock
40     private AbstractWriteTx writeOnlyTx1;
41     @Mock
42     private AbstractWriteTx writeOnlyTx2;
43     @Mock
44     private AbstractWriteTx writeOnlyTx3;
45     @Mock
46     private Registration registration1;
47     @Mock
48     private Registration registration2;
49     @Mock
50     private Registration registration3;
51     @Captor
52     private ArgumentCaptor<TxListener> captor;
53     private TxChain chain;
54
55     @Before
56     public void setUp() {
57         when(broker.newReadOnlyTransaction()).thenReturn(readOnlyTx);
58         when(broker.newWriteOnlyTransaction()).thenReturn(writeOnlyTx1)
59                 .thenReturn(writeOnlyTx2).thenReturn(writeOnlyTx3);
60         when(writeOnlyTx1.addListener(any())).thenReturn(registration1);
61         when(writeOnlyTx2.addListener(any())).thenReturn(registration2);
62         when(writeOnlyTx3.addListener(any())).thenReturn(registration3);
63         chain = new TxChain(broker);
64         chain.addCallback(listener);
65     }
66
67     @Test
68     public void testNewReadOnlyTransactionPrevSubmitted() {
69         chain.newWriteOnlyTransaction();
70         verify(writeOnlyTx1).addListener(captor.capture());
71         captor.getValue().onTransactionSubmitted(writeOnlyTx1);
72         chain.newReadOnlyTransaction();
73     }
74
75     @Test
76     public void testNewReadOnlyTransactionPrevNotSubmitted() {
77         chain.newWriteOnlyTransaction();
78         assertThrows(IllegalStateException.class, chain::newReadOnlyTransaction);
79     }
80
81     @Test
82     public void testNewReadWriteTransactionPrevSubmitted() {
83         chain.newReadWriteTransaction();
84         verify(writeOnlyTx1).addListener(captor.capture());
85         captor.getValue().onTransactionSubmitted(writeOnlyTx1);
86         chain.newReadWriteTransaction();
87     }
88
89     @Test
90     public void testNewReadWriteTransactionPrevNotSubmitted() {
91         chain.newReadWriteTransaction();
92         assertThrows(IllegalStateException.class, chain::newReadWriteTransaction);
93     }
94
95     @Test
96     public void testNewWriteOnlyTransactionPrevSubmitted() {
97         chain.newWriteOnlyTransaction();
98         verify(writeOnlyTx1).addListener(captor.capture());
99         captor.getValue().onTransactionSubmitted(writeOnlyTx1);
100         chain.newWriteOnlyTransaction();
101     }
102
103     @Test
104     public void testNewWriteOnlyTransactionPrevNotSubmitted() {
105         chain.newWriteOnlyTransaction();
106         assertThrows(IllegalStateException.class, chain::newWriteOnlyTransaction);
107     }
108
109     @Test
110     public void testCloseAfterFinished() {
111         chain.close();
112         verify(listener).onSuccess(Empty.value());
113         assertThrows(DOMTransactionChainClosedException.class, chain::newReadOnlyTransaction);
114     }
115
116     @Test
117     public void testChainFail() {
118         final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
119         verify(writeOnlyTx1).addListener(captor.capture());
120         writeTx.commit();
121         final TransactionCommitFailedException cause = new TransactionCommitFailedException("fail");
122         captor.getValue().onTransactionFailed(writeOnlyTx1, cause);
123         verify(registration1).close();
124         verify(listener).onFailure(cause);
125     }
126
127     @Test
128     public void testChainSuccess() {
129         final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
130         chain.close();
131         verify(writeOnlyTx1).addListener(captor.capture());
132         writeTx.commit();
133         captor.getValue().onTransactionSuccessful(writeOnlyTx1);
134         verify(registration1).close();
135         verify(listener).onSuccess(Empty.value());
136     }
137
138     @Test
139     public void testCancel() {
140         final AbstractWriteTx writeTx = chain.newWriteOnlyTransaction();
141         verify(writeOnlyTx1).addListener(captor.capture());
142         writeTx.cancel();
143         captor.getValue().onTransactionCancelled(writeOnlyTx1);
144         chain.newWriteOnlyTransaction();
145     }
146
147     @Test
148     public void testMultiplePendingTransactions() {
149         //create 1st tx
150         final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
151         final var captor1 = ArgumentCaptor.forClass(TxListener.class);
152         verify(writeOnlyTx1).addListener(captor1.capture());
153         //submit 1st tx
154         writeTx1.commit();
155         captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
156
157         //create 2nd tx
158         final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
159         final var captor2 = ArgumentCaptor.forClass(TxListener.class);
160         verify(writeTx2).addListener(captor2.capture());
161         //submit 2nd tx
162         writeTx2.commit();
163         captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
164
165         //create 3rd tx
166         final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
167         final var captor3 = ArgumentCaptor.forClass(TxListener.class);
168         verify(writeTx3).addListener(captor3.capture());
169         //cancel 3rd tx
170         writeTx3.cancel();
171         captor3.getValue().onTransactionCancelled(writeOnlyTx3);
172
173         //close chain
174         chain.close();
175
176         //complete first two transactions successfully
177         captor1.getValue().onTransactionSuccessful(writeOnlyTx1);
178         captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
179
180         verify(registration1).close();
181         verify(registration2).close();
182         verify(registration3).close();
183         verify(listener).onSuccess(Empty.value());
184     }
185
186     @Test
187     public void testMultiplePendingTransactionsFail() {
188         //create 1st tx
189         final AbstractWriteTx writeTx1 = chain.newWriteOnlyTransaction();
190         final var captor1 = ArgumentCaptor.forClass(TxListener.class);
191         verify(writeOnlyTx1).addListener(captor1.capture());
192         //submit 1st tx
193         writeTx1.commit();
194         captor1.getValue().onTransactionSubmitted(writeOnlyTx1);
195
196         //create 2nd tx
197         final AbstractWriteTx writeTx2 = chain.newWriteOnlyTransaction();
198         final var captor2 = ArgumentCaptor.forClass(TxListener.class);
199         verify(writeTx2).addListener(captor2.capture());
200         //submit 2nd tx
201         writeTx2.commit();
202         captor2.getValue().onTransactionSubmitted(writeOnlyTx2);
203
204         //create 3rd tx
205         final AbstractWriteTx writeTx3 = chain.newWriteOnlyTransaction();
206         final var captor3 = ArgumentCaptor.forClass(TxListener.class);
207         verify(writeTx3).addListener(captor3.capture());
208
209         chain.close();
210
211         //fail 1st transaction
212         final Exception cause1 = new Exception("fail");
213         captor1.getValue().onTransactionFailed(writeOnlyTx1, cause1);
214         //current unsubmitted transaction should be cancelled
215         verify(writeTx3).cancel();
216         captor3.getValue().onTransactionCancelled(writeTx3);
217         //2nd transaction success
218         captor2.getValue().onTransactionSuccessful(writeOnlyTx2);
219
220         verify(registration1).close();
221         verify(registration2).close();
222         verify(registration3).close();
223         verify(listener).onFailure(cause1);
224         // 1 transaction failed, onTransactionChainSuccessful must not be called
225         verify(listener, never()).onSuccess(any());
226     }
227 }