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.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;
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.spi.node.ImmutableNodes;
58 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
59 import org.w3c.dom.DOMException;
61 @RunWith(MockitoJUnitRunner.StrictStubs.class)
62 public final class MdsalRestconfStrategyTest extends AbstractRestconfStrategyTest {
63 private static final DatabindContext MODULES_DATABIND = DatabindContext.ofModel(
64 YangParserTestUtils.parseYangResourceDirectory("/modules"));
67 private DOMDataTreeReadWriteTransaction readWrite;
69 private DOMDataBroker dataBroker;
71 private DOMDataTreeReadTransaction read;
73 private DOMRpcService rpcService;
75 private DOMSchemaService schemaService;
77 private DOMMountPointService mountPointService;
79 private DOMMountPoint mountPoint;
81 private NetconfDataTreeService netconfService;
84 public void before() {
85 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
86 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
90 RestconfStrategy newStrategy(final DatabindContext databind) {
91 return new MdsalRestconfStrategy(databind, dataBroker, rpcService, null, null, mountPointService);
94 private @NonNull RestconfStrategy modulesStrategy() {
95 return newStrategy(MODULES_DATABIND);
99 RestconfStrategy testDeleteDataStrategy() {
100 // assert that data to delete exists
101 when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
102 .thenReturn(immediateTrueFluentFuture());
103 return jukeboxStrategy();
107 RestconfStrategy testNegativeDeleteDataStrategy() {
108 // assert that data to delete does NOT exist
109 when(readWrite.exists(LogicalDatastoreType.CONFIGURATION, YangInstanceIdentifier.of()))
110 .thenReturn(immediateFalseFluentFuture());
111 return jukeboxStrategy();
115 RestconfStrategy testPostListDataStrategy(final MapEntryNode entryNode, final YangInstanceIdentifier node) {
116 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, node);
117 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, node, entryNode);
118 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
119 return jukeboxStrategy();
123 RestconfStrategy testPostDataFailStrategy(final DOMException domException) {
124 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
125 doReturn(immediateFailedFluentFuture(domException)).when(readWrite).commit();
126 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
127 return jukeboxStrategy();
131 public void testPutContainerData() {
132 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
133 doReturn(read).when(dataBroker).newReadOnlyTransaction();
134 doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
135 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
136 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
138 jukeboxStrategy().putData(JUKEBOX_IID, EMPTY_JUKEBOX, null);
139 verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
140 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
144 public void testPutLeafData() {
145 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
146 doReturn(read).when(dataBroker).newReadOnlyTransaction();
147 doReturn(immediateFalseFluentFuture()).when(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
148 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
149 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
151 jukeboxStrategy().putData(GAP_IID, GAP_LEAF, null);
152 verify(read).exists(LogicalDatastoreType.CONFIGURATION, GAP_IID);
153 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, GAP_IID, GAP_LEAF);
158 public void testPutListData() {
159 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
160 doReturn(read).when(dataBroker).newReadOnlyTransaction();
161 doReturn(immediateFalseFluentFuture())
162 .when(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
163 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
164 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
166 jukeboxStrategy().putData(JUKEBOX_IID, JUKEBOX_WITH_BANDS, null);
167 verify(read).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
168 verify(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, JUKEBOX_WITH_BANDS);
172 RestconfStrategy testPostContainerDataStrategy() {
173 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID);
174 doNothing().when(readWrite).put(LogicalDatastoreType.CONFIGURATION, JUKEBOX_IID, EMPTY_JUKEBOX);
175 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
176 return jukeboxStrategy();
180 RestconfStrategy testPatchContainerDataStrategy() {
181 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
182 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
183 return jukeboxStrategy();
187 RestconfStrategy testPatchLeafDataStrategy() {
188 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
189 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
190 return jukeboxStrategy();
194 RestconfStrategy testPatchListDataStrategy() {
195 doReturn(readWrite).when(dataBroker).newReadWriteTransaction();
196 doReturn(CommitInfo.emptyFluentFuture()).when(readWrite).commit();
197 return jukeboxStrategy();
201 RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy() {
202 return jukeboxStrategy();
206 RestconfStrategy testPatchDataCreateAndDeleteStrategy() {
207 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION, PLAYER_IID);
208 doReturn(immediateTrueFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
209 CREATE_AND_DELETE_TARGET);
210 return jukeboxStrategy();
214 RestconfStrategy testPatchMergePutContainerStrategy() {
215 return jukeboxStrategy();
219 RestconfStrategy deleteNonexistentDataTestStrategy() {
220 doReturn(immediateFalseFluentFuture()).when(readWrite).exists(LogicalDatastoreType.CONFIGURATION,
221 CREATE_AND_DELETE_TARGET);
222 return jukeboxStrategy();
226 void assertTestDeleteNonexistentData(final PatchStatusContext status, final PatchStatusEntity edit) {
227 assertNull(status.globalErrors());
228 final var editErrors = edit.getEditErrors();
229 assertEquals(1, editErrors.size());
230 final var editError = editErrors.get(0);
231 assertEquals("Data does not exist", editError.getErrorMessage());
232 assertEquals(ErrorType.PROTOCOL, editError.getErrorType());
233 assertEquals(ErrorTag.DATA_MISSING, editError.getErrorTag());
237 RestconfStrategy readDataConfigTestStrategy() {
238 doReturn(read).when(dataBroker).newReadOnlyTransaction();
239 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
240 .read(LogicalDatastoreType.CONFIGURATION, PATH);
241 return mockStrategy();
245 RestconfStrategy readAllHavingOnlyConfigTestStrategy() {
246 doReturn(read).when(dataBroker).newReadOnlyTransaction();
247 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
248 .read(LogicalDatastoreType.CONFIGURATION, PATH);
249 doReturn(immediateFluentFuture(Optional.empty())).when(read)
250 .read(LogicalDatastoreType.OPERATIONAL, PATH);
251 return mockStrategy();
255 RestconfStrategy readAllHavingOnlyNonConfigTestStrategy() {
256 doReturn(read).when(dataBroker).newReadOnlyTransaction();
257 doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
258 .read(LogicalDatastoreType.OPERATIONAL, PATH_2);
259 doReturn(immediateFluentFuture(Optional.empty())).when(read)
260 .read(LogicalDatastoreType.CONFIGURATION, PATH_2);
261 return mockStrategy();
265 RestconfStrategy readDataNonConfigTestStrategy() {
266 doReturn(read).when(dataBroker).newReadOnlyTransaction();
267 doReturn(immediateFluentFuture(Optional.of(DATA_2))).when(read)
268 .read(LogicalDatastoreType.OPERATIONAL, PATH_2);
269 return mockStrategy();
273 RestconfStrategy readContainerDataAllTestStrategy() {
274 doReturn(read).when(dataBroker).newReadOnlyTransaction();
275 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
276 .read(LogicalDatastoreType.CONFIGURATION, PATH);
277 doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
278 .read(LogicalDatastoreType.OPERATIONAL, PATH);
279 return mockStrategy();
283 RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy() {
284 doReturn(read).when(dataBroker).newReadOnlyTransaction();
285 doReturn(immediateFluentFuture(Optional.of(DATA_3))).when(read)
286 .read(LogicalDatastoreType.CONFIGURATION, PATH);
287 doReturn(immediateFluentFuture(Optional.of(DATA_4))).when(read)
288 .read(LogicalDatastoreType.OPERATIONAL, PATH);
289 return mockStrategy();
293 RestconfStrategy readListDataAllTestStrategy() {
294 doReturn(read).when(dataBroker).newReadOnlyTransaction();
295 doReturn(immediateFluentFuture(Optional.of(LIST_DATA))).when(read)
296 .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
297 doReturn(immediateFluentFuture(Optional.of(LIST_DATA_2))).when(read)
298 .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
299 return mockStrategy();
303 RestconfStrategy readOrderedListDataAllTestStrategy() {
304 doReturn(read).when(dataBroker).newReadOnlyTransaction();
305 doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_1))).when(read)
306 .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
307 doReturn(immediateFluentFuture(Optional.of(ORDERED_MAP_NODE_2))).when(read)
308 .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
309 return mockStrategy();
313 RestconfStrategy readUnkeyedListDataAllTestStrategy() {
314 doReturn(read).when(dataBroker).newReadOnlyTransaction();
315 doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_1))).when(read)
316 .read(LogicalDatastoreType.OPERATIONAL, PATH_3);
317 doReturn(immediateFluentFuture(Optional.of(UNKEYED_LIST_NODE_2))).when(read)
318 .read(LogicalDatastoreType.CONFIGURATION, PATH_3);
319 return mockStrategy();
323 RestconfStrategy readLeafListDataAllTestStrategy() {
324 doReturn(read).when(dataBroker).newReadOnlyTransaction();
325 doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_1))).when(read)
326 .read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
327 doReturn(immediateFluentFuture(Optional.of(LEAF_SET_NODE_2))).when(read)
328 .read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
329 return mockStrategy();
333 RestconfStrategy readOrderedLeafListDataAllTestStrategy() {
334 doReturn(read).when(dataBroker).newReadOnlyTransaction();
335 doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_1))).when(read)
336 .read(LogicalDatastoreType.OPERATIONAL, LEAF_SET_NODE_PATH);
337 doReturn(immediateFluentFuture(Optional.of(ORDERED_LEAF_SET_NODE_2))).when(read)
338 .read(LogicalDatastoreType.CONFIGURATION, LEAF_SET_NODE_PATH);
339 return mockStrategy();
343 RestconfStrategy readDataWrongPathOrNoContentTestStrategy() {
344 doReturn(read).when(dataBroker).newReadOnlyTransaction();
345 doReturn(immediateFluentFuture(Optional.empty())).when(read).read(LogicalDatastoreType.CONFIGURATION, PATH_2);
346 return mockStrategy();
350 public void readLeafWithDefaultParameters() {
351 final var data = ImmutableNodes.newContainerBuilder()
352 .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
353 .withChild(ImmutableNodes.leafNode(QName.create(BASE, "exampleLeaf"), "i am leaf"))
355 final var path = YangInstanceIdentifier.of(CONT_QNAME);
356 doReturn(read).when(dataBroker).newReadOnlyTransaction();
357 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
358 .read(LogicalDatastoreType.CONFIGURATION, path);
359 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
360 .read(LogicalDatastoreType.OPERATIONAL, path);
362 assertEquals(data, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
366 public void readContainerWithDefaultParameters() {
367 final var exampleList = new NodeIdentifier(QName.create(BASE, "exampleList"));
368 final var data = ImmutableNodes.newContainerBuilder()
369 .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
370 .withChild(ImmutableNodes.newUnkeyedListBuilder()
371 .withNodeIdentifier(exampleList)
372 .withChild(ImmutableNodes.newUnkeyedListEntryBuilder()
373 .withNodeIdentifier(exampleList)
374 .withChild(ImmutableNodes.newContainerBuilder()
375 .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "containerBool")))
376 .withChild(ImmutableNodes.leafNode(QName.create(BASE, "leafBool"), true))
378 .addChild(ImmutableNodes.newContainerBuilder()
379 .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "containerInt")))
380 .withChild(ImmutableNodes.leafNode(QName.create(BASE, "leafInt"), 12))
385 final var path = YangInstanceIdentifier.of(CONT_QNAME);
386 doReturn(read).when(dataBroker).newReadOnlyTransaction();
387 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
388 .read(LogicalDatastoreType.CONFIGURATION, path);
389 doReturn(immediateFluentFuture(Optional.of(data))).when(read)
390 .read(LogicalDatastoreType.OPERATIONAL, path);
392 assertEquals(data, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
396 public void readLeafInListWithDefaultParameters() {
397 final var exampleList = new NodeIdentifier(QName.create(BASE, "exampleList"));
398 final var content = ImmutableNodes.newContainerBuilder()
399 .withNodeIdentifier(new NodeIdentifier(CONT_QNAME))
400 .withChild(ImmutableNodes.newUnkeyedListBuilder()
401 .withNodeIdentifier(exampleList)
402 .withChild(ImmutableNodes.newUnkeyedListEntryBuilder()
403 .withNodeIdentifier(exampleList)
404 .addChild(ImmutableNodes.leafNode(QName.create(BASE, "leafInList"), "I am leaf in list"))
408 final var path = YangInstanceIdentifier.of(CONT_QNAME);
409 doReturn(read).when(dataBroker).newReadOnlyTransaction();
410 doReturn(immediateFluentFuture(Optional.of(content))).when(read)
411 .read(LogicalDatastoreType.CONFIGURATION, path);
412 doReturn(immediateFluentFuture(Optional.of(content))).when(read)
413 .read(LogicalDatastoreType.OPERATIONAL, path);
415 assertEquals(content, modulesStrategy().readData(ContentParam.ALL, path, WithDefaultsParam.TRIM));
419 public void testGetRestconfStrategyLocal() {
420 final var strategy = jukeboxStrategy();
421 assertEquals(new StrategyAndTail(strategy, ApiPath.empty()), strategy.resolveStrategy(ApiPath.empty()));
425 public void testGetRestconfStrategyMountDataBroker() throws Exception {
426 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
427 doReturn(Optional.of(dataBroker)).when(mountPoint).getService(DOMDataBroker.class);
428 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
429 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
430 .getService(DOMSchemaService.class);
431 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
432 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
433 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
435 final var strategy = jukeboxStrategy();
436 final var result = strategy.resolveStrategy(ApiPath.parse("yang-ext:mount"));
437 assertEquals(ApiPath.empty(), result.tail());
438 assertNotSame(strategy, assertInstanceOf(MdsalRestconfStrategy.class, result.strategy()));
442 public void testGetRestconfStrategyMountNetconfService() throws Exception {
443 doReturn(Optional.of(netconfService)).when(mountPoint).getService(NetconfDataTreeService.class);
444 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
445 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
446 .getService(DOMSchemaService.class);
447 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
448 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
449 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
451 final var strategy = jukeboxStrategy();
452 final var result = strategy.resolveStrategy(ApiPath.parse("yang-ext:mount"));
453 assertEquals(ApiPath.empty(), result.tail());
454 assertInstanceOf(NetconfRestconfStrategy.class, result.strategy());
458 public void testGetRestconfStrategyMountNone() throws Exception {
459 doReturn(JUKEBOX_IID).when(mountPoint).getIdentifier();
460 doReturn(Optional.empty()).when(mountPoint).getService(NetconfDataTreeService.class);
461 doReturn(Optional.empty()).when(mountPoint).getService(DOMDataBroker.class);
462 doReturn(Optional.empty()).when(mountPoint).getService(DOMMountPointService.class);
463 doReturn(Optional.empty()).when(mountPoint).getService(DOMActionService.class);
464 doReturn(Optional.of(rpcService)).when(mountPoint).getService(DOMRpcService.class);
465 doReturn(Optional.of(new FixedDOMSchemaService(JUKEBOX_SCHEMA))).when(mountPoint)
466 .getService(DOMSchemaService.class);
467 doReturn(Optional.of(mountPoint)).when(mountPointService).getMountPoint(YangInstanceIdentifier.of());
469 final var strategy = jukeboxStrategy();
470 final var mountPath = ApiPath.parse("yang-ext:mount");
472 final var ex = assertThrows(RestconfDocumentedException.class, () -> strategy.resolveStrategy(mountPath));
473 final var errors = ex.getErrors();
474 assertEquals(1, errors.size());
475 final var error = errors.get(0);
476 assertEquals(ErrorType.APPLICATION, error.getErrorType());
477 assertEquals(ErrorTag.OPERATION_FAILED, error.getErrorTag());
478 assertEquals("Could not find a supported access interface in mount point", error.getErrorMessage());
479 assertEquals(JUKEBOX_IID, error.getErrorPath());