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.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
12 import static org.junit.jupiter.api.Assertions.assertNotNull;
13 import static org.junit.jupiter.api.Assertions.assertNotSame;
14 import static org.junit.jupiter.api.Assertions.assertNull;
15 import static org.junit.jupiter.api.Assertions.assertThrows;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.doNothing;
18 import static org.mockito.Mockito.doReturn;
19 import static org.mockito.Mockito.verify;
20 import static org.mockito.Mockito.when;
21 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
22 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
23 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
24 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
26 import com.google.common.collect.ImmutableMap;
27 import java.util.Optional;
28 import org.eclipse.jdt.annotation.NonNull;
29 import org.junit.jupiter.api.Test;
30 import org.junit.jupiter.api.extension.ExtendWith;
31 import org.mockito.Mock;
32 import org.mockito.junit.jupiter.MockitoExtension;
33 import org.opendaylight.mdsal.common.api.CommitInfo;
34 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
35 import org.opendaylight.mdsal.dom.api.DOMActionService;
36 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
37 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
38 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
39 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
40 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
41 import org.opendaylight.mdsal.dom.api.DOMRpcService;
42 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
43 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
44 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
45 import org.opendaylight.restconf.api.ApiPath;
46 import org.opendaylight.restconf.api.ErrorMessage;
47 import org.opendaylight.restconf.api.query.ContentParam;
48 import org.opendaylight.restconf.api.query.WithDefaultsParam;
49 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy.StrategyAndTail;
50 import org.opendaylight.restconf.server.api.DataPutResult;
51 import org.opendaylight.restconf.server.api.DatabindContext;
52 import org.opendaylight.restconf.server.api.PatchStatusContext;
53 import org.opendaylight.restconf.server.api.PatchStatusEntity;
54 import org.opendaylight.restconf.server.api.ServerException;
55 import org.opendaylight.yangtools.yang.common.ErrorTag;
56 import org.opendaylight.yangtools.yang.common.ErrorType;
57 import org.opendaylight.yangtools.yang.common.QName;
58 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
59 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
60 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
61 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
62 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
63 import org.w3c.dom.DOMException;
65 @ExtendWith(MockitoExtension.class)
66 final class MdsalRestconfStrategyTest extends AbstractRestconfStrategyTest {
67 private static final DatabindContext MODULES_DATABIND = DatabindContext.ofModel(
68 YangParserTestUtils.parseYangResourceDirectory("/modules"));
71 private DOMDataTreeReadWriteTransaction readWrite;
73 private DOMDataBroker dataBroker;
75 private DOMDataTreeReadTransaction read;
77 private DOMRpcService rpcService;
79 private DOMSchemaService schemaService;
81 private DOMMountPointService mountPointService;
83 private DOMMountPoint mountPoint;
85 private NetconfDataTreeService netconfService;
88 RestconfStrategy newStrategy(final DatabindContext databind) {
89 return new MdsalRestconfStrategy(databind, dataBroker, ImmutableMap.of(), rpcService, null, null,
93 private @NonNull RestconfStrategy modulesStrategy() {
94 return newStrategy(MODULES_DATABIND);
98 RestconfStrategy testDeleteDataStrategy() {
99 // assert that data to delete exists
100 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
101 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
102 when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
103 .thenReturn(immediateTrueFluentFuture());
104 return jukeboxStrategy();
108 RestconfStrategy testNegativeDeleteDataStrategy() {
109 // assert that data to delete does NOT exist
110 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
111 when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
112 .thenReturn(immediateFalseFluentFuture());
113 return jukeboxStrategy();
117 RestconfStrategy testPostListDataStrategy(final MapEntryNode entryNode, final YangInstanceIdentifier node) {
118 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
119 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
120 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
121 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
122 return jukeboxStrategy();
126 RestconfStrategy testPostDataFailStrategy(final DOMException domException) {
127 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
128 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
129 doReturn(immediateFailedFluentFuture(domException)).when(readWrite).commit();
130 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
131 return jukeboxStrategy();
135 void testPutContainerData() {
136 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
137 doReturn(read).when(dataBroker).newReadOnlyTransaction();
138 doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
139 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
140 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
142 jukeboxStrategy().putData(dataPutRequest, JUKEBOX_IID, EMPTY_JUKEBOX, null);
143 verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
144 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
145 verify(dataPutRequest).completeWith(any(DataPutResult.class));
149 void testPutLeafData() {
150 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
151 doReturn(read).when(dataBroker).newReadOnlyTransaction();
152 doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
153 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
154 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
156 jukeboxStrategy().putData(dataPutRequest, GAP_IID, GAP_LEAF, null);
157 verify(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
158 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
159 verify(dataPutRequest).completeWith(any(DataPutResult.class));
163 void testPutListData() {
164 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
165 doReturn(read).when(dataBroker).newReadOnlyTransaction();
166 doReturn(immediateFalseFluentFuture())
167 .when(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
168 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
169 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
171 jukeboxStrategy().putData(dataPutRequest, JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
172 verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
173 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
174 verify(dataPutRequest).completeWith(any(DataPutResult.class));
178 RestconfStrategy testPostContainerDataStrategy() {
179 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
180 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
181 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
182 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
183 return jukeboxStrategy();
187 RestconfStrategy testPatchContainerDataStrategy() {
188 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
189 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
190 return jukeboxStrategy();
194 RestconfStrategy testPatchLeafDataStrategy() {
195 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
196 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
197 return jukeboxStrategy();
201 RestconfStrategy testPatchListDataStrategy() {
202 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
203 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
204 return jukeboxStrategy();
208 RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
209 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
210 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
211 return jukeboxStrategy();
215 RestconfStrategy testPatchDataCreateAndDeleteStrategy() {
216 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
217 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
218 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, PLAYER_IID);
219 doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
220 CREATE_AND_DELETE_TARGET);
221 return jukeboxStrategy();
225 RestconfStrategy testPatchMergePutContainerStrategy() {
226 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
227 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
228 return jukeboxStrategy();
232 RestconfStrategy deleteNonexistentDataTestStrategy() {
233 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
234 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
235 CREATE_AND_DELETE_TARGET);
236 return jukeboxStrategy();
240 void assertTestDeleteNonexistentData(final PatchStatusContext status, final PatchStatusEntity edit) {
241 assertNull(status.globalErrors());
242 final var editErrors = edit.getEditErrors();
243 assertEquals(1, editErrors.size());
244 final var editError = editErrors.get(0);
245 assertEquals(new ErrorMessage("Data does not exist"), editError.message());
246 assertEquals(ErrorType.PROTOCOL, editError.type());
247 assertEquals(ErrorTag.DATA_MISSING, editError.tag());
251 RestconfStrategy readDataConfigTestStrategy() {
252 doReturn(read).when(dataBroker).newReadOnlyTransaction();
253 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
254 .read(LogicalDatastoreType.CONFIGURATION, PATH);
255 return mockStrategy();
259 RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
260 doReturn(read).when(dataBroker).newReadOnlyTransaction();
261 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
262 .read(LogicalDatastoreType.CONFIGURATION, PATH);
263 doReturn(immediateFluentFuture(Optional.empty())).when(read)
264 .read(LogicalDatastoreType.OPERATIONAL, PATH);
265 return mockStrategy();
269 RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
270 doReturn(read).when(dataBroker).newReadOnlyTransaction();
271 doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
272 .read(LogicalDatastoreType.OPERATIONAL, PATH_2);
273 doReturn(immediateFluentFuture(Optional.empty())).when(read)
274 .read(LogicalDatastoreType.CONFIGURATION, PATH_2);
275 return mockStrategy();
279 RestconfStrategy readDataNonConfigTestStrategy() {
280 doReturn(read).when(dataBroker).newReadOnlyTransaction();
281 doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
282 .read(LogicalDatastoreType.OPERATIONAL, PATH_2);
283 return mockStrategy();
287 RestconfStrategy readContainerDataAllTestStrategy() {
288 doReturn(read).when(dataBroker).newReadOnlyTransaction();
289 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
290 .read(LogicalDatastoreType.CONFIGURATION, PATH);
291 doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
292 .read(LogicalDatastoreType.OPERATIONAL, PATH);
293 return mockStrategy();
297 RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
298 doReturn(read).when(dataBroker).newReadOnlyTransaction();
299 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
300 .read(LogicalDatastoreType.CONFIGURATION, PATH);
301 doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
302 .read(LogicalDatastoreType.OPERATIONAL, PATH);
303 return mockStrategy();
307 RestconfStrategy readListDataAllTestStrategy() {
308 doReturn(read).when(dataBroker).newReadOnlyTransaction();
309 doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(read)
310 .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
311 doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(read)
312 .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
313 return mockStrategy();
317 RestconfStrategy readOrderedListDataAllTestStrategy() {
318 doReturn(read).when(dataBroker).newReadOnlyTransaction();
319 doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(read)
320 .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
321 doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(read)
322 .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
323 return mockStrategy();
327 RestconfStrategy readUnkeyedListDataAllTestStrategy() {
328 doReturn(read).when(dataBroker).newReadOnlyTransaction();
329 doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(read)
330 .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
331 doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(read)
332 .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
333 return mockStrategy();
337 RestconfStrategy readLeafListDataAllTestStrategy() {
338 doReturn(read).when(dataBroker).newReadOnlyTransaction();
339 doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_1))).when(read)
340 .read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
341 doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(read)
342 .read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
343 return mockStrategy();
347 RestconfStrategy readOrderedLeafListDataAllTestStrategy() {
348 doReturn(read).when(dataBroker).newReadOnlyTransaction();
349 doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_1))).when(read)
350 .read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
351 doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(read)
352 .read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
353 return mockStrategy();
357 RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
358 doReturn(read).when(dataBroker).newReadOnlyTransaction();
359 doReturn(immediateFluentFuture(Optional.empty())).when(read).read(LogicalDatastoreType.CONFIGURATION, PATH_2);
360 return mockStrategy();
364 void readLeafWithDefaultParameters() throws Exception {
365 final var data = ImmutableNodes.newContainerBuilder()
366 .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
367 .withChild(ImmutableNodes.leafNode(QName.create(BASE, "exampleLeaf"), "i am leaf"))
369 final var path = YangInstanceIdentifier.of(CONT_QNAME);
370 doReturn(read).when(dataBroker).newReadOnlyTransaction();
371 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
372 .read(LogicalDatastoreType.CONFIGURATION, path);
373 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
374 .read(LogicalDatastoreType.OPERATIONAL, path);
376 assertEquals(data, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
380 void readContainerWithDefaultParameters() throws Exception {
381 final var exampleList = new NodeIdentifier(QName.create(BASE, "exampleList"));
382 final var data = ImmutableNodes.newContainerBuilder()
383 .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
384 .withChild(ImmutableNodes.newUnkeyedListBuilder()
385 .withNodeIdentifier(exampleList)
386 .withChild(ImmutableNodes.newUnkeyedListEntryBuilder()
387 .withNodeIdentifier(exampleList)
388 .withChild(ImmutableNodes.newContainerBuilder()
389 .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "containerBool")))
390 .withChild(ImmutableNodes.leafNode(QName.create(BASE, "leafBool"), true))
392 .addChild(ImmutableNodes.newContainerBuilder()
393 .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "containerInt")))
394 .withChild(ImmutableNodes.leafNode(QName.create(BASE, "leafInt"), 12))
399 final var path = YangInstanceIdentifier.of(CONT_QNAME);
400 doReturn(read).when(dataBroker).newReadOnlyTransaction();
401 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
402 .read(LogicalDatastoreType.CONFIGURATION, path);
403 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
404 .read(LogicalDatastoreType.OPERATIONAL, path);
406 assertEquals(data, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
410 void readLeafInListWithDefaultParameters() throws Exception {
411 final var exampleList = new NodeIdentifier(QName.create(BASE, "exampleList"));
412 final var content = ImmutableNodes.newContainerBuilder()
413 .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
414 .withChild(ImmutableNodes.newUnkeyedListBuilder()
415 .withNodeIdentifier(exampleList)
416 .withChild(ImmutableNodes.newUnkeyedListEntryBuilder()
417 .withNodeIdentifier(exampleList)
418 .addChild(ImmutableNodes.leafNode(QName.create(BASE, "leafInList"), "I am leaf in list"))
422 final var path = YangInstanceIdentifier.of(CONT_QNAME);
423 doReturn(read).when(dataBroker).newReadOnlyTransaction();
424 doReturn(immediateFluentFuture(Optional.of(content))).when(read)
425 .read(LogicalDatastoreType.CONFIGURATION, path);
426 doReturn(immediateFluentFuture(Optional.of(content))).when(read)
427 .read(LogicalDatastoreType.OPERATIONAL, path);
429 assertEquals(content, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
433 void testGetRestconfStrategyLocal() throws Exception {
434 final var strategy = jukeboxStrategy();
435 assertEquals(new StrategyAndTail(strategy, ApiPath.empty()), strategy.resolveStrategy(ApiPath.empty()));
439 void testGetRestconfStrategyMountDataBroker() throws Exception {
440 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
441 doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
442 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
443 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
444 .getService(DOMSchemaService.class);
445 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
446 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
447 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
449 final var strategy = jukeboxStrategy();
450 final var result = strategy.resolveStrategy(ApiPath.parse("yang-ext:mount"));
451 assertEquals(ApiPath.empty(), result.tail());
452 assertNotSame(strategy, assertInstanceOf(MdsalRestconfStrategy.class, result.strategy()));
456 void testGetRestconfStrategyMountNetconfService() throws Exception {
457 doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
458 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
459 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
460 .getService(DOMSchemaService.class);
461 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
462 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
463 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
465 final var strategy = jukeboxStrategy();
466 final var result = strategy.resolveStrategy(ApiPath.parse("yang-ext:mount"));
467 assertEquals(ApiPath.empty(), result.tail());
468 assertInstanceOf(NetconfRestconfStrategy.class, result.strategy());
472 void testGetRestconfStrategyMountNone() throws Exception {
473 doReturn(JUKEBOX_IID).when(mountPoint).getIdentifier();
474 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
475 doReturn(Optional.empty()).when(mountPoint).getService(DOMDataBroker.class);
476 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
477 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
478 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
479 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
480 .getService(DOMSchemaService.class);
481 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
483 final var strategy = jukeboxStrategy();
484 final var mountPath = ApiPath.parse("yang-ext:mount");
486 final var errors = assertThrows(ServerException.class, () -> strategy.resolveStrategy(mountPath)).errors();
487 assertEquals(1, errors.size());
488 final var error = errors.get(0);
489 assertEquals(ErrorType.APPLICATION, error.type());
490 assertEquals(ErrorTag.OPERATION_FAILED, error.tag());
491 assertEquals(new ErrorMessage("Could not find a supported access interface in mount point"), error.message());
492 final var path = error.path();
494 assertEquals(JUKEBOX_IID, path.path());