Bump upstreams
[netconf.git] / restconf / restconf-nb / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / transactions / MdsalRestconfStrategyTest.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.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertInstanceOf;
12 import static org.junit.jupiter.api.Assertions.assertNotSame;
13 import static org.junit.jupiter.api.Assertions.assertNull;
14 import static org.junit.jupiter.api.Assertions.assertThrows;
15 import static org.mockito.Mockito.doNothing;
16 import static org.mockito.Mockito.doReturn;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
19 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFailedFluentFuture;
20 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
21 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFluentFuture;
22 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateTrueFluentFuture;
23
24 import java.util.Optional;
25 import org.eclipse.jdt.annotation.NonNull;
26 import org.junit.Before;
27 import org.junit.Test;
28 import org.junit.runner.RunWith;
29 import org.mockito.Mock;
30 import org.mockito.junit.MockitoJUnitRunner;
31 import org.opendaylight.mdsal.common.api.CommitInfo;
32 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
33 import org.opendaylight.mdsal.dom.api.DOMActionService;
34 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
35 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
36 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
37 import org.opendaylight.mdsal.dom.api.DOMMountPoint;
38 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
39 import org.opendaylight.mdsal.dom.api.DOMRpcService;
40 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
41 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
42 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
43 import org.opendaylight.restconf.api.ApiPath;
44 import org.opendaylight.restconf.api.query.ContentParam;
45 import org.opendaylight.restconf.api.query.WithDefaultsParam;
46 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
47 import org.opendaylight.restconf.common.patch.PatchStatusContext;
48 import org.opendaylight.restconf.common.patch.PatchStatusEntity;
49 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.RestconfStrategy.StrategyAndTail;
50 import org.opendaylight.restconf.server.api.DatabindContext;
51 import org.opendaylight.yangtools.yang.common.ErrorTag;
52 import org.opendaylight.yangtools.yang.common.ErrorType;
53 import org.opendaylight.yangtools.yang.common.QName;
54 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
55 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
56 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
57 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
58 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
59 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
60 import org.w3c.dom.DOMException;
61
62 @RunWith(MockitoJUnitRunner.StrictStubs.class)
63 public final class MdsalRestconfStrategyTest extends AbstractRestconfStrategyTest {
64     private static final DatabindContext MODULES_DATABIND = DatabindContext.ofModel(
65         YangParserTestUtils.parseYangResourceDirectory("/modules"));
66
67     @Mock
68     private DOMDataTreeReadWriteTransaction readWrite;
69     @Mock
70     private DOMDataBroker dataBroker;
71     @Mock
72     private DOMDataTreeReadTransaction read;
73     @Mock
74     private DOMRpcService rpcService;
75     @Mock
76     private DOMSchemaService schemaService;
77     @Mock
78     private DOMMountPointService mountPointService;
79     @Mock
80     private DOMMountPoint mountPoint;
81     @Mock
82     private NetconfDataTreeService netconfService;
83
84     @Before
85     public void before() {
86         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
87         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
88     }
89
90     @Override
91     RestconfStrategy newStrategy(final DatabindContext databind) {
92         return new MdsalRestconfStrategy(databind, dataBroker, rpcService, null, null, mountPointService);
93     }
94
95     private @NonNull RestconfStrategy modulesStrategy() {
96         return newStrategy(MODULES_DATABIND);
97     }
98
99     @Override
100     RestconfStrategy testDeleteDataStrategy() {
101         // assert that data to delete exists
102         when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
103             .thenReturn(immediateTrueFluentFuture());
104         return jukeboxStrategy();
105     }
106
107     @Override
108     RestconfStrategy testNegativeDeleteDataStrategy() {
109         // assert that data to delete does NOT exist
110         when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
111             .thenReturn(immediateFalseFluentFuture());
112         return jukeboxStrategy();
113     }
114
115     @Override
116     RestconfStrategy testPostListDataStrategy(final MapEntryNode entryNode, final YangInstanceIdentifier node) {
117         doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
118         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
119         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
120         return jukeboxStrategy();
121     }
122
123     @Override
124     RestconfStrategy testPostDataFailStrategy(final DOMException domException) {
125         doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
126         doReturn(immediateFailedFluentFuture(domException)).when(readWrite).commit();
127         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
128         return jukeboxStrategy();
129     }
130
131     @Test
132     public void testPutContainerData() {
133         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
134         doReturn(read).when(dataBroker).newReadOnlyTransaction();
135         doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
136         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
137         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
138
139         jukeboxStrategy().putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
140         verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
141         verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
142     }
143
144     @Test
145     public void testPutLeafData() {
146         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
147         doReturn(read).when(dataBroker).newReadOnlyTransaction();
148         doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
149         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
150         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
151
152         jukeboxStrategy().putData(GAP_IID, GAP_LEAF, null);
153         verify(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
154         verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
155     }
156
157
158     @Test
159     public void testPutListData() {
160         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
161         doReturn(read).when(dataBroker).newReadOnlyTransaction();
162         doReturn(immediateFalseFluentFuture())
163                 .when(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
164         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
165         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
166
167         jukeboxStrategy().putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
168         verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
169         verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
170     }
171
172     @Override
173     RestconfStrategy testPostContainerDataStrategy() {
174         doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
175         doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
176         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
177         return jukeboxStrategy();
178     }
179
180     @Override
181     RestconfStrategy testPatchContainerDataStrategy() {
182         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
183         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
184         return jukeboxStrategy();
185     }
186
187     @Override
188     RestconfStrategy testPatchLeafDataStrategy() {
189         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
190         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
191         return jukeboxStrategy();
192     }
193
194     @Override
195     RestconfStrategy testPatchListDataStrategy() {
196         doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
197         doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
198         return jukeboxStrategy();
199     }
200
201     @Override
202     RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
203         return jukeboxStrategy();
204     }
205
206     @Override
207     RestconfStrategy testPatchDataCreateAndDeleteStrategy() {
208         doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, PLAYER_IID);
209         doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
210             CREATE_AND_DELETE_TARGET);
211         return jukeboxStrategy();
212     }
213
214     @Override
215     RestconfStrategy testPatchMergePutContainerStrategy() {
216         return jukeboxStrategy();
217     }
218
219     @Override
220     RestconfStrategy deleteNonexistentDataTestStrategy() {
221         doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
222             CREATE_AND_DELETE_TARGET);
223         return jukeboxStrategy();
224     }
225
226     @Override
227     void assertTestDeleteNonexistentData(final PatchStatusContext status, final PatchStatusEntity edit) {
228         assertNull(status.globalErrors());
229         final var editErrors = edit.getEditErrors();
230         assertEquals(1, editErrors.size());
231         final var editError = editErrors.get(0);
232         assertEquals("Data does not exist", editError.getErrorMessage());
233         assertEquals(ErrorType.PROTOCOL, editError.getErrorType());
234         assertEquals(ErrorTag.DATA_MISSING, editError.getErrorTag());
235     }
236
237     @Override
238     RestconfStrategy readDataConfigTestStrategy() {
239         doReturn(read).when(dataBroker).newReadOnlyTransaction();
240         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
241             .read(LogicalDatastoreType.CONFIGURATION, PATH);
242         return mockStrategy();
243     }
244
245     @Override
246     RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
247         doReturn(read).when(dataBroker).newReadOnlyTransaction();
248         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
249             .read(LogicalDatastoreType.CONFIGURATION, PATH);
250         doReturn(immediateFluentFuture(Optional.empty())).when(read)
251             .read(LogicalDatastoreType.OPERATIONAL, PATH);
252         return mockStrategy();
253     }
254
255     @Override
256     RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
257         doReturn(read).when(dataBroker).newReadOnlyTransaction();
258         doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
259             .read(LogicalDatastoreType.OPERATIONAL, PATH_2);
260         doReturn(immediateFluentFuture(Optional.empty())).when(read)
261             .read(LogicalDatastoreType.CONFIGURATION, PATH_2);
262         return mockStrategy();
263     }
264
265     @Override
266     RestconfStrategy readDataNonConfigTestStrategy() {
267         doReturn(read).when(dataBroker).newReadOnlyTransaction();
268         doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
269             .read(LogicalDatastoreType.OPERATIONAL, PATH_2);
270         return mockStrategy();
271     }
272
273     @Override
274     RestconfStrategy readContainerDataAllTestStrategy() {
275         doReturn(read).when(dataBroker).newReadOnlyTransaction();
276         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
277             .read(LogicalDatastoreType.CONFIGURATION, PATH);
278         doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
279             .read(LogicalDatastoreType.OPERATIONAL, PATH);
280         return mockStrategy();
281     }
282
283     @Override
284     RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
285         doReturn(read).when(dataBroker).newReadOnlyTransaction();
286         doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
287             .read(LogicalDatastoreType.CONFIGURATION, PATH);
288         doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
289             .read(LogicalDatastoreType.OPERATIONAL, PATH);
290         return mockStrategy();
291     }
292
293     @Override
294     RestconfStrategy readListDataAllTestStrategy() {
295         doReturn(read).when(dataBroker).newReadOnlyTransaction();
296         doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(read)
297             .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
298         doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(read)
299             .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
300         return mockStrategy();
301     }
302
303     @Override
304     RestconfStrategy readOrderedListDataAllTestStrategy() {
305         doReturn(read).when(dataBroker).newReadOnlyTransaction();
306         doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(read)
307             .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
308         doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(read)
309             .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
310         return mockStrategy();
311     }
312
313     @Override
314     RestconfStrategy readUnkeyedListDataAllTestStrategy() {
315         doReturn(read).when(dataBroker).newReadOnlyTransaction();
316         doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(read)
317             .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
318         doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(read)
319             .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
320         return mockStrategy();
321     }
322
323     @Override
324     RestconfStrategy readLeafListDataAllTestStrategy() {
325         doReturn(read).when(dataBroker).newReadOnlyTransaction();
326         doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_1))).when(read)
327             .read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
328         doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(read)
329             .read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
330         return mockStrategy();
331     }
332
333     @Override
334     RestconfStrategy readOrderedLeafListDataAllTestStrategy() {
335         doReturn(read).when(dataBroker).newReadOnlyTransaction();
336         doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_1))).when(read)
337             .read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
338         doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(read)
339             .read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
340         return mockStrategy();
341     }
342
343     @Override
344     RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
345         doReturn(read).when(dataBroker).newReadOnlyTransaction();
346         doReturn(immediateFluentFuture(Optional.empty())).when(read).read(LogicalDatastoreType.CONFIGURATION, PATH_2);
347         return mockStrategy();
348     }
349
350     @Test
351     public void readLeafWithDefaultParameters() {
352         final var data = Builders.containerBuilder()
353             .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
354             .withChild(ImmutableNodes.leafNode(QName.create(BASE, "exampleLeaf"), "i am leaf"))
355             .build();
356         final var path = YangInstanceIdentifier.of(CONT_QNAME);
357         doReturn(read).when(dataBroker).newReadOnlyTransaction();
358         doReturn(immediateFluentFuture(Optional.of(data))).when(read)
359                 .read(LogicalDatastoreType.CONFIGURATION, path);
360         doReturn(immediateFluentFuture(Optional.of(data))).when(read)
361                 .read(LogicalDatastoreType.OPERATIONAL, path);
362
363         assertEquals(data, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
364     }
365
366     @Test
367     public void readContainerWithDefaultParameters() {
368         final var exampleList = new NodeIdentifier(QName.create(BASE, "exampleList"));
369         final var data = Builders.containerBuilder()
370             .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
371             .withChild(Builders.unkeyedListBuilder()
372                 .withNodeIdentifier(exampleList)
373                 .withChild(Builders.unkeyedListEntryBuilder()
374                     .withNodeIdentifier(exampleList)
375                     .withChild(Builders.containerBuilder()
376                         .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "containerBool")))
377                         .withChild(ImmutableNodes.leafNode(QName.create(BASE, "leafBool"), true))
378                         .build())
379                     .addChild(Builders.containerBuilder()
380                         .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "containerInt")))
381                         .withChild(ImmutableNodes.leafNode(QName.create(BASE, "leafInt"), 12))
382                         .build())
383                     .build())
384                 .build())
385             .build();
386         final var path = YangInstanceIdentifier.of(CONT_QNAME);
387         doReturn(read).when(dataBroker).newReadOnlyTransaction();
388         doReturn(immediateFluentFuture(Optional.of(data))).when(read)
389                 .read(LogicalDatastoreType.CONFIGURATION, path);
390         doReturn(immediateFluentFuture(Optional.of(data))).when(read)
391                 .read(LogicalDatastoreType.OPERATIONAL, path);
392
393         assertEquals(data, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
394     }
395
396     @Test
397     public void readLeafInListWithDefaultParameters() {
398         final var exampleList = new NodeIdentifier(QName.create(BASE, "exampleList"));
399         final var content = Builders.containerBuilder()
400             .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
401             .withChild(Builders.unkeyedListBuilder()
402                 .withNodeIdentifier(exampleList)
403                 .withChild(Builders.unkeyedListEntryBuilder()
404                     .withNodeIdentifier(exampleList)
405                     .addChild(ImmutableNodes.leafNode(QName.create(BASE, "leafInList"), "I am leaf in list"))
406                     .build())
407                 .build())
408             .build();
409         final var path = YangInstanceIdentifier.of(CONT_QNAME);
410         doReturn(read).when(dataBroker).newReadOnlyTransaction();
411         doReturn(immediateFluentFuture(Optional.of(content))).when(read)
412                 .read(LogicalDatastoreType.CONFIGURATION, path);
413         doReturn(immediateFluentFuture(Optional.of(content))).when(read)
414                 .read(LogicalDatastoreType.OPERATIONAL, path);
415
416         assertEquals(content, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
417     }
418
419     @Test
420     public void testGetRestconfStrategyLocal() {
421         final var strategy = jukeboxStrategy();
422         assertEquals(new StrategyAndTail(strategy, ApiPath.empty()), strategy.resolveStrategy(ApiPath.empty()));
423     }
424
425     @Test
426     public void testGetRestconfStrategyMountDataBroker() throws Exception {
427         doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
428         doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
429         doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
430         doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
431             .getService(DOMSchemaService.class);
432         doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
433         doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
434         doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
435
436         final var strategy = jukeboxStrategy();
437         final var result = strategy.resolveStrategy(ApiPath.parse("yang-ext:mount"));
438         assertEquals(ApiPath.empty(), result.tail());
439         assertNotSame(strategy, assertInstanceOf(MdsalRestconfStrategy.class, result.strategy()));
440     }
441
442     @Test
443     public void testGetRestconfStrategyMountNetconfService() throws Exception {
444         doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
445         doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
446         doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
447             .getService(DOMSchemaService.class);
448         doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
449         doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
450         doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
451
452         final var strategy = jukeboxStrategy();
453         final var result = strategy.resolveStrategy(ApiPath.parse("yang-ext:mount"));
454         assertEquals(ApiPath.empty(), result.tail());
455         assertInstanceOf(NetconfRestconfStrategy.class, result.strategy());
456     }
457
458     @Test
459     public void testGetRestconfStrategyMountNone() throws Exception {
460         doReturn(JUKEBOX_IID).when(mountPoint).getIdentifier();
461         doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
462         doReturn(Optional.empty()).when(mountPoint).getService(DOMDataBroker.class);
463         doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
464         doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
465         doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
466         doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
467             .getService(DOMSchemaService.class);
468         doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
469
470         final var strategy = jukeboxStrategy();
471         final var mountPath = ApiPath.parse("yang-ext:mount");
472
473         final var ex = assertThrows(RestconfDocumentedException.class, () -> strategy.resolveStrategy(mountPath));
474         final var errors = ex.getErrors();
475         assertEquals(1, errors.size());
476         final var error = errors.get(0);
477         assertEquals(ErrorType.APPLICATION, error.getErrorType());
478         assertEquals(ErrorTag.OPERATION_FAILED, error.getErrorTag());
479         assertEquals("Could not find a supported access interface in mount point", error.getErrorMessage());
480         assertEquals(JUKEBOX_IID, error.getErrorPath());
481     }
482 }