5b218715737b6a34032aacc0beb01826e2da1444
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / SimpleShardDataTreeCohortTest.java
1 /*
2  * Copyright (c) 2015 Brocade Communications 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.controller.cluster.datastore;
9
10 import static org.junit.Assert.assertSame;
11 import static org.mockito.Matchers.any;
12 import static org.mockito.Mockito.doAnswer;
13 import static org.mockito.Mockito.doNothing;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.never;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.verifyNoMoreInteractions;
19
20 import com.google.common.primitives.UnsignedLong;
21 import com.google.common.util.concurrent.FutureCallback;
22 import java.util.Collections;
23 import java.util.Optional;
24 import java.util.concurrent.CompletableFuture;
25 import java.util.concurrent.Future;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.mockito.Mock;
29 import org.mockito.MockitoAnnotations;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
31 import org.opendaylight.yangtools.yang.data.api.schema.tree.ConflictingModificationAppliedException;
32 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate;
33 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidateTip;
34 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
35 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
36 import scala.concurrent.Promise;
37
38 /**
39  * Unit tests for SimpleShardDataTreeCohort.
40  *
41  * @author Thomas Pantelis
42  */
43 public class SimpleShardDataTreeCohortTest extends AbstractTest {
44     @Mock
45     private ShardDataTree mockShardDataTree;
46
47     @Mock
48     private DataTreeModification mockModification;
49
50     @Mock
51     private CompositeDataTreeCohort mockUserCohorts;
52
53     @Mock
54     private FutureCallback<DataTreeCandidate> mockPreCallback;
55
56     private SimpleShardDataTreeCohort cohort;
57
58     @Before
59     public void setup() throws Exception {
60         MockitoAnnotations.initMocks(this);
61
62         doNothing().when(mockUserCohorts).commit();
63         doReturn(Optional.empty()).when(mockUserCohorts).abort();
64
65         cohort = new SimpleShardDataTreeCohort.Normal(mockShardDataTree, mockModification, nextTransactionId(),
66             mockUserCohorts);
67     }
68
69     @Test
70     public void testCanCommitSuccess() throws Exception {
71         canCommitSuccess();
72     }
73
74     private void canCommitSuccess() {
75         doAnswer(invocation -> {
76             invocation.getArgumentAt(0, SimpleShardDataTreeCohort.class).successfulCanCommit();
77             return null;
78         }).when(mockShardDataTree).startCanCommit(cohort);
79
80         @SuppressWarnings("unchecked")
81         final FutureCallback<Void> callback = mock(FutureCallback.class);
82         cohort.canCommit(callback);
83
84         verify(callback).onSuccess(null);
85         verifyNoMoreInteractions(callback);
86     }
87
88     private void testValidatationPropagates(final Exception cause) throws DataValidationFailedException {
89         doAnswer(invocation -> {
90             invocation.getArgumentAt(0, SimpleShardDataTreeCohort.class).failedCanCommit(cause);
91             return null;
92         }).when(mockShardDataTree).startCanCommit(cohort);
93
94         @SuppressWarnings("unchecked")
95         final FutureCallback<Void> callback = mock(FutureCallback.class);
96         cohort.canCommit(callback);
97
98         verify(callback).onFailure(cause);
99         verifyNoMoreInteractions(callback);
100     }
101
102     @Test
103     public void testCanCommitWithConflictingModEx() throws DataValidationFailedException {
104         testValidatationPropagates(new ConflictingModificationAppliedException(YangInstanceIdentifier.EMPTY, "mock"));
105     }
106
107     @Test
108     public void testCanCommitWithDataValidationEx() throws DataValidationFailedException {
109         testValidatationPropagates(new DataValidationFailedException(YangInstanceIdentifier.EMPTY, "mock"));
110     }
111
112     @Test
113     public void testCanCommitWithIllegalArgumentEx() throws DataValidationFailedException {
114         testValidatationPropagates(new IllegalArgumentException("mock"));
115     }
116
117     private DataTreeCandidateTip preCommitSuccess() {
118         final DataTreeCandidateTip mockCandidate = mock(DataTreeCandidateTip.class);
119         doAnswer(invocation -> {
120             invocation.getArgumentAt(0, SimpleShardDataTreeCohort.class).successfulPreCommit(mockCandidate);
121             return null;
122         }).when(mockShardDataTree).startPreCommit(cohort);
123
124         @SuppressWarnings("unchecked")
125         final FutureCallback<DataTreeCandidate> callback = mock(FutureCallback.class);
126         cohort.preCommit(callback);
127
128         verify(callback).onSuccess(mockCandidate);
129         verifyNoMoreInteractions(callback);
130
131         assertSame("getCandidate", mockCandidate, cohort.getCandidate());
132
133         return mockCandidate;
134     }
135
136     @Test
137     public void testPreCommitAndCommitSuccess() throws Exception {
138         canCommitSuccess();
139         final DataTreeCandidateTip candidate = preCommitSuccess();
140
141         doAnswer(invocation -> {
142             invocation.getArgumentAt(0, SimpleShardDataTreeCohort.class).successfulCommit(UnsignedLong.valueOf(0));
143             return null;
144         }).when(mockShardDataTree).startCommit(cohort, candidate);
145
146         @SuppressWarnings("unchecked")
147         final FutureCallback<UnsignedLong> mockCommitCallback = mock(FutureCallback.class);
148         cohort.commit(mockCommitCallback);
149
150         verify(mockCommitCallback).onSuccess(any(UnsignedLong.class));
151         verifyNoMoreInteractions(mockCommitCallback);
152
153         verify(mockUserCohorts).commit();
154     }
155
156     @Test
157     public void testPreCommitWithIllegalArgumentEx() throws Exception {
158         canCommitSuccess();
159
160         final Exception cause = new IllegalArgumentException("mock");
161         doAnswer(invocation -> {
162             invocation.getArgumentAt(0, SimpleShardDataTreeCohort.class).failedPreCommit(cause);
163             return null;
164         }).when(mockShardDataTree).startPreCommit(cohort);
165
166         @SuppressWarnings("unchecked")
167         final FutureCallback<DataTreeCandidate> callback = mock(FutureCallback.class);
168         cohort.preCommit(callback);
169
170         verify(callback).onFailure(cause);
171         verifyNoMoreInteractions(callback);
172
173         verify(mockUserCohorts).abort();
174     }
175
176     @Test
177     public void testPreCommitWithReportedFailure() throws Exception {
178         canCommitSuccess();
179
180         final Exception cause = new IllegalArgumentException("mock");
181         cohort.reportFailure(cause);
182
183         @SuppressWarnings("unchecked")
184         final FutureCallback<DataTreeCandidate> callback = mock(FutureCallback.class);
185         cohort.preCommit(callback);
186
187         verify(callback).onFailure(cause);
188         verifyNoMoreInteractions(callback);
189
190         verify(mockShardDataTree, never()).startPreCommit(cohort);
191     }
192
193     @Test
194     public void testCommitWithIllegalArgumentEx() {
195         canCommitSuccess();
196         final DataTreeCandidateTip candidate = preCommitSuccess();
197
198         final Exception cause = new IllegalArgumentException("mock");
199         doAnswer(invocation -> {
200             invocation.getArgumentAt(0, SimpleShardDataTreeCohort.class).failedCommit(cause);
201             return null;
202         }).when(mockShardDataTree).startCommit(cohort, candidate);
203
204         @SuppressWarnings("unchecked")
205         final FutureCallback<UnsignedLong> callback = mock(FutureCallback.class);
206         cohort.commit(callback);
207
208         verify(callback).onFailure(cause);
209         verifyNoMoreInteractions(callback);
210
211         verify(mockUserCohorts).abort();
212     }
213
214     private static Future<?> abort(final ShardDataTreeCohort cohort) {
215         final CompletableFuture<Void> f = new CompletableFuture<>();
216         cohort.abort(new FutureCallback<Void>() {
217             @Override
218             public void onSuccess(final Void result) {
219                 f.complete(null);
220             }
221
222             @Override
223             public void onFailure(final Throwable failure) {
224                 f.completeExceptionally(failure);
225             }
226         });
227
228         return f;
229     }
230
231     @Test
232     public void testAbort() throws Exception {
233         doReturn(true).when(mockShardDataTree).startAbort(cohort);
234
235         abort(cohort).get();
236         verify(mockShardDataTree).startAbort(cohort);
237     }
238
239     @Test
240     public void testAbortWithCohorts() throws Exception {
241         doReturn(true).when(mockShardDataTree).startAbort(cohort);
242
243         final Promise<Iterable<Object>> cohortFuture = akka.dispatch.Futures.promise();
244         doReturn(Optional.of(cohortFuture.future())).when(mockUserCohorts).abort();
245
246         final Future<?> abortFuture = abort(cohort);
247
248         cohortFuture.success(Collections.emptyList());
249
250         abortFuture.get();
251         verify(mockShardDataTree).startAbort(cohort);
252     }
253 }