2 * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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
8 package org.opendaylight.restconf.nb.rfc8040.rests.transactions;
10 import static org.junit.Assert.assertEquals;
11 import static org.mockito.ArgumentMatchers.any;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.mock;
14 import static org.mockito.Mockito.verify;
15 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
16 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
18 import com.google.common.util.concurrent.Futures;
19 import java.util.Optional;
20 import org.junit.Before;
21 import org.junit.Test;
22 import org.junit.runner.RunWith;
23 import org.mockito.Mock;
24 import org.mockito.junit.MockitoJUnitRunner;
25 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
26 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
27 import org.opendaylight.mdsal.dom.spi.DefaultDOMRpcResult;
28 import org.opendaylight.netconf.api.NetconfDocumentedException;
29 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
30 import org.opendaylight.restconf.common.patch.PatchStatusContext;
31 import org.opendaylight.yangtools.yang.common.ErrorSeverity;
32 import org.opendaylight.yangtools.yang.common.ErrorTag;
33 import org.opendaylight.yangtools.yang.common.ErrorType;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
36 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
37 import org.w3c.dom.DOMException;
39 @RunWith(MockitoJUnitRunner.StrictStubs.class)
40 public final class NetconfRestconfStrategyTest extends AbstractRestconfStrategyTest {
42 private NetconfDataTreeService netconfService;
45 public void before() {
46 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
47 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
48 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
49 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).lock();
50 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
51 .delete(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of());
52 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).merge(any(), any(),
57 RestconfStrategy testDeleteDataStrategy() {
58 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
62 RestconfStrategy testNegativeDeleteDataStrategy() {
63 doReturn(Futures.immediateFailedFuture(new TransactionCommitFailedException(
64 "Commit of transaction " + this + " failed", new NetconfDocumentedException("id",
65 ErrorType.RPC, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR)))).when(netconfService).commit();
66 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
70 RestconfStrategy testPostContainerDataStrategy() {
71 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
72 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
73 .create(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
74 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
78 RestconfStrategy testPostListDataStrategy(final MapEntryNode entryNode, final YangInstanceIdentifier node) {
79 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
81 .merge(any(), any(), any(), any());
82 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
83 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).create(
84 LogicalDatastoreType.CONFIGURATION, node, entryNode, Optional.empty());
85 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
89 RestconfStrategy testPostDataFailStrategy(final DOMException domException) {
90 doReturn(immediateFailedFluentFuture(domException)).when(netconfService)
92 .create(any(), any(), any(), any());
93 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).discardChanges();
94 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).unlock();
95 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
99 RestconfStrategy testPatchContainerDataStrategy() {
100 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).merge(any(), any(),any(),
102 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
106 RestconfStrategy testPatchLeafDataStrategy() {
107 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
108 .merge(any(), any(), any(), any());
109 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
110 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
114 RestconfStrategy testPatchListDataStrategy() {
115 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
116 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
117 .merge(any(), any(),any(),any());
118 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
122 public void testPutCreateContainerData() {
123 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(JUKEBOX_IID);
124 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
125 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
126 .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
128 new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
129 verify(netconfService).lock();
130 verify(netconfService).getConfig(JUKEBOX_IID);
131 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
136 public void testPutReplaceContainerData() {
137 doReturn(immediateFluentFuture(Optional.of(mock(NormalizedNode.class)))).when(netconfService)
138 .getConfig(JUKEBOX_IID);
139 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
140 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
141 .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX, Optional.empty());
143 new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
144 verify(netconfService).getConfig(JUKEBOX_IID);
145 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX,
150 public void testPutCreateLeafData() {
151 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(GAP_IID);
152 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
153 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
154 .replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
156 new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(GAP_IID, GAP_LEAF, null);
157 verify(netconfService).getConfig(GAP_IID);
158 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
162 public void testPutReplaceLeafData() {
163 doReturn(immediateFluentFuture(Optional.of(mock(NormalizedNode.class)))).when(netconfService)
165 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
166 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
167 .replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
169 new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null).putData(GAP_IID, GAP_LEAF, null);
170 verify(netconfService).getConfig(GAP_IID);
171 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF, Optional.empty());
175 public void testPutCreateListData() {
176 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(JUKEBOX_IID);
177 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
178 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
179 .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
181 new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null)
182 .putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
183 verify(netconfService).getConfig(JUKEBOX_IID);
184 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
189 public void testPutReplaceListData() {
190 doReturn(immediateFluentFuture(Optional.of(mock(NormalizedNode.class)))).when(netconfService)
191 .getConfig(JUKEBOX_IID);
192 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService).commit();
193 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
194 .replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS, Optional.empty());
196 new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null)
197 .putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
198 verify(netconfService).getConfig(JUKEBOX_IID);
199 verify(netconfService).replace(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS,
204 RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
205 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
206 .remove(LogicalDatastoreType.CONFIGURATION, ARTIST_IID);
207 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
208 // FIXME: exact match
209 .replace(any(), any(), any(), any());
210 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
214 RestconfStrategy testPatchDataCreateAndDeleteStrategy() {
215 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
216 .create(LogicalDatastoreType.CONFIGURATION, PLAYER_IID, EMPTY_JUKEBOX, Optional.empty());
217 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
218 .delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
219 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
223 RestconfStrategy testPatchMergePutContainerStrategy() {
224 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
228 RestconfStrategy deleteNonexistentDataTestStrategy() {
229 doReturn(Futures.immediateFailedFuture(
230 new TransactionCommitFailedException("Commit of transaction " + this + " failed",
231 new NetconfDocumentedException("id", ErrorType.RPC, ErrorTag.DATA_MISSING, ErrorSeverity.ERROR))))
232 .when(netconfService).commit();
233 doReturn(Futures.immediateFuture(new DefaultDOMRpcResult())).when(netconfService)
234 .delete(LogicalDatastoreType.CONFIGURATION, CREATE_AND_DELETE_TARGET);
235 return new NetconfRestconfStrategy(JUKEBOX_SCHEMA, netconfService, null);
239 void assertTestDeleteNonexistentData(final PatchStatusContext status) {
240 final var globalErrors = status.globalErrors();
241 assertEquals(1, globalErrors.size());
242 final var globalError = globalErrors.get(0);
243 assertEquals(ErrorType.PROTOCOL, globalError.getErrorType());
244 assertEquals(ErrorTag.DATA_MISSING, globalError.getErrorTag());
248 RestconfStrategy readDataConfigTestStrategy() {
249 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
250 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
254 RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
255 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
256 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).get(PATH);
257 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
261 RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
262 doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
263 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
264 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
268 RestconfStrategy readDataNonConfigTestStrategy() {
269 doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(netconfService).get(PATH_2);
270 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
274 RestconfStrategy readContainerDataAllTestStrategy() {
275 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
276 doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
277 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
281 RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
282 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(netconfService).getConfig(PATH);
283 doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(netconfService).get(PATH);
284 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
288 RestconfStrategy readListDataAllTestStrategy() {
289 doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(netconfService).get(PATH_3);
290 doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(netconfService).getConfig(PATH_3);
291 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
295 RestconfStrategy readOrderedListDataAllTestStrategy() {
296 doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(netconfService).get(PATH_3);
297 doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(netconfService).getConfig(PATH_3);
298 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
302 RestconfStrategy readUnkeyedListDataAllTestStrategy() {
303 doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(netconfService).get(PATH_3);
304 doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(netconfService).getConfig(PATH_3);
305 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
309 RestconfStrategy readLeafListDataAllTestStrategy() {
310 doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_1))).when(netconfService)
311 .get(LEAF_SET_NODE_PATH);
312 doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(netconfService)
313 .getConfig(LEAF_SET_NODE_PATH);
314 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
318 RestconfStrategy readOrderedLeafListDataAllTestStrategy() {
319 doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_1))).when(netconfService)
320 .get(LEAF_SET_NODE_PATH);
321 doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(netconfService)
322 .getConfig(LEAF_SET_NODE_PATH);
323 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);
327 RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
328 doReturn(immediateFluentFuture(Optional.empty())).when(netconfService).getConfig(PATH_2);
329 return new NetconfRestconfStrategy(mockSchemaContext, netconfService, null);