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