Bump upstreams
[netconf.git] / restconf / restconf-nb / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / transactions / NetconfRestconfStrategyTest.java
1 /*
2  * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.restconf.nb.rfc8040.rests.transactions;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNull;
13 import static org.mockito.ArgumentMatchers.any;
14 import static org.mockito.Mockito.doReturn;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.verify;
17 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
18 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
19
20 import com.google.common.util.concurrent.Futures;
21 import java.util.Optional;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.junit.runner.RunWith;
25 import org.mockito.Mock;
26 import org.mockito.junit.MockitoJUnitRunner;
27 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
28 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
29 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
30 import org.opendaylight.netconf.api.NetconfDocumentedException;
31 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
32 import org.opendaylight.restconf.common.patch.PatchStatusContext;
33 import org.opendaylight.restconf.common.patch.PatchStatusEntity;
34 import org.opendaylight.restconf.server.api.DatabindContext;
35 import org.opendaylight.yangtools.yang.common.ErrorSeverity;
36 import org.opendaylight.yangtools.yang.common.ErrorTag;
37 import org.opendaylight.yangtools.yang.common.ErrorType;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
41 import org.w3c.dom.DOMException;
42
43 @RunWith(MockitoJUnitRunner.StrictStubs.class)
44 public final class NetconfRestconfStrategyTest extends AbstractRestconfStrategyTest {
45     @Mock
46     private NetconfDataTreeService netconfService;
47
48     @Before
49     public void before() {
50         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
51         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
52         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
53         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).lock();
54         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
55             .delete(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of());
56         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).merge(any(), any(),
57             any(), any());
58     }
59
60     @Override
61     RestconfStrategy newStrategy(final DatabindContext databind) {
62         return new NetconfRestconfStrategy(databind, netconfService, null, null, null, null);
63     }
64
65     @Override
66     RestconfStrategy testDeleteDataStrategy() {
67         return jukeboxStrategy();
68     }
69
70     @Override
71     RestconfStrategy testNegativeDeleteDataStrategy() {
72         doReturn(Futures.immediateFailedFuture(new TransactionCommitFailedException(
73             "Commit of transaction " + this + " failed", new NetconfDocumentedException("id",
74                 ErrorType.RPC, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR)))).when(netconfService).commit();
75         return jukeboxStrategy();
76     }
77
78     @Override
79     RestconfStrategy testPostContainerDataStrategy() {
80         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
81         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
82             .create(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
83         return jukeboxStrategy();
84     }
85
86     @Override
87     RestconfStrategy testPostListDataStrategy(final MapEntryNode entryNode, final YangInstanceIdentifier node) {
88         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
89             // FIXME: exact match
90             .merge(any(), any(), any(), any());
91         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
92         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).create(
93             LogicalDatastoreType.CONFIGURATION, node, entryNode, Optional.empty());
94         return jukeboxStrategy();
95     }
96
97     @Override
98     RestconfStrategy testPostDataFailStrategy(final DOMException domException) {
99         doReturn(immediateFailedFluentFuture(domException)).when(netconfService)
100             // FIXME: exact match
101             .create(any(), any(), any(), any());
102         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
103         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
104         return jukeboxStrategy();
105     }
106
107     @Override
108     RestconfStrategy testPatchContainerDataStrategy() {
109         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).merge(any(), any(),any(),
110             any());
111         return jukeboxStrategy();
112     }
113
114     @Override
115     RestconfStrategy testPatchLeafDataStrategy() {
116         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
117             .merge(any(), any(), any(), any());
118         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
119         return jukeboxStrategy();
120     }
121
122     @Override
123     RestconfStrategy testPatchListDataStrategy() {
124         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
125         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
126             .merge(any(), any(),any(),any());
127         return jukeboxStrategy();
128     }
129
130     @Test
131     public void testPutCreateContainerData() {
132         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(JUKEBOX_IID);
133         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
134         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
135             .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
136
137         jukeboxStrategy().putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
138         verify(netconfService).lock();
139         verify(netconfService).getConfig(JUKEBOX_IID);
140         verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
141             Optional.empty());
142     }
143
144     @Test
145     public void testPutReplaceContainerData() {
146         doReturn(immediateFluentFuture(Optional.of(mock(ContainerNode.class)))).when(netconfService)
147             .getConfig(JUKEBOX_IID);
148         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
149         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
150             .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
151
152         jukeboxStrategy().putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
153         verify(netconfService).getConfig(JUKEBOX_IID);
154         verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
155             Optional.empty());
156     }
157
158     @Test
159     public void testPutCreateLeafData() {
160         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(GAP_IID);
161         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
162         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
163             .replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
164
165         jukeboxStrategy().putData(GAP_IID, GAP_LEAF, null);
166         verify(netconfService).getConfig(GAP_IID);
167         verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
168     }
169
170     @Test
171     public void testPutReplaceLeafData() {
172         doReturn(immediateFluentFuture(Optional.of(mock(ContainerNode.class)))).when(netconfService)
173             .getConfig(GAP_IID);
174         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
175         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
176             .replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
177
178         jukeboxStrategy().putData(GAP_IID, GAP_LEAF, null);
179         verify(netconfService).getConfig(GAP_IID);
180         verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
181     }
182
183     @Test
184     public void testPutCreateListData() {
185         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(JUKEBOX_IID);
186         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
187         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
188             .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
189
190         jukeboxStrategy().putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
191         verify(netconfService).getConfig(JUKEBOX_IID);
192         verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
193             Optional.empty());
194     }
195
196     @Test
197     public void testPutReplaceListData() {
198         doReturn(immediateFluentFuture(Optional.of(mock(ContainerNode.class)))).when(netconfService)
199             .getConfig(JUKEBOX_IID);
200         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
201         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
202             .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
203
204         jukeboxStrategy().putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
205         verify(netconfService).getConfig(JUKEBOX_IID);
206         verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
207             Optional.empty());
208     }
209
210     @Override
211     RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
212         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
213             .remove(LogicalDatastoreType.CONFIGURATION, ARTIST_IID);
214         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
215             // FIXME: exact match
216             .replace(any(), any(), any(), any());
217         return jukeboxStrategy();
218     }
219
220     @Override
221     RestconfStrategy testPatchDataCreateAndDeleteStrategy() {
222         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
223             .create(LogicalDatastoreType.CONFIGURATION, PLAYER_IID, EMPTY_JUKEBOX, Optional.empty());
224         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
225             .delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
226         return jukeboxStrategy();
227     }
228
229     @Override
230     RestconfStrategy testPatchMergePutContainerStrategy() {
231         return jukeboxStrategy();
232     }
233
234     @Override
235     RestconfStrategy deleteNonexistentDataTestStrategy() {
236         doReturn(Futures.immediateFailedFuture(
237             new TransactionCommitFailedException("Commit of transaction " + this + " failed",
238                 new NetconfDocumentedException("id", ErrorType.RPC, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR))))
239             .when(netconfService).commit();
240         doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
241             .delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
242         return jukeboxStrategy();
243     }
244
245     @Override
246     void assertTestDeleteNonexistentData(final PatchStatusContext status, final PatchStatusEntity edit) {
247         assertNull(edit.getEditErrors());
248         final var globalErrors = status.globalErrors();
249         assertNotNull(globalErrors);
250         assertEquals(1, globalErrors.size());
251         final var globalError = globalErrors.get(0);
252         assertEquals("Data does not exist", globalError.getErrorMessage());
253         assertEquals(ErrorType.PROTOCOL, globalError.getErrorType());
254         assertEquals(ErrorTag.DATA_MISSING, globalError.getErrorTag());
255     }
256
257     @Override
258     RestconfStrategy readDataConfigTestStrategy() {
259         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
260         return mockStrategy();
261     }
262
263     @Override
264     RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
265         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
266         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(PATH);
267         return mockStrategy();
268     }
269
270     @Override
271     RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
272         doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
273         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
274         return mockStrategy();
275     }
276
277     @Override
278     RestconfStrategy readDataNonConfigTestStrategy() {
279         doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
280         return mockStrategy();
281     }
282
283     @Override
284     RestconfStrategy readContainerDataAllTestStrategy() {
285         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
286         doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
287         return mockStrategy();
288     }
289
290     @Override
291     RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
292         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
293         doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
294         return mockStrategy();
295     }
296
297     @Override
298     RestconfStrategy readListDataAllTestStrategy() {
299         doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(netconfService).get(PATH_3);
300         doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(netconfService).getConfig(PATH_3);
301         return mockStrategy();
302     }
303
304     @Override
305     RestconfStrategy readOrderedListDataAllTestStrategy() {
306         doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(netconfService).get(PATH_3);
307         doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(netconfService).getConfig(PATH_3);
308         return mockStrategy();
309     }
310
311     @Override
312     RestconfStrategy readUnkeyedListDataAllTestStrategy() {
313         doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(netconfService).get(PATH_3);
314         doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(netconfService).getConfig(PATH_3);
315         return mockStrategy();
316     }
317
318     @Override
319     RestconfStrategy readLeafListDataAllTestStrategy() {
320         doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_1))).when(netconfService)
321             .get(LEAF_SET_NODE_PATH);
322         doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(netconfService)
323             .getConfig(LEAF_SET_NODE_PATH);
324         return mockStrategy();
325     }
326
327     @Override
328     RestconfStrategy readOrderedLeafListDataAllTestStrategy() {
329         doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_1))).when(netconfService)
330             .get(LEAF_SET_NODE_PATH);
331         doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(netconfService)
332             .getConfig(LEAF_SET_NODE_PATH);
333         return mockStrategy();
334     }
335
336     @Override
337     RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
338         doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
339         return mockStrategy();
340     }
341 }