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.hamcrest.CoreMatchers.containsString;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.jupiter.api.Assertions.assertEquals;
13 import static org.junit.jupiter.api.Assertions.assertFalse;
14 import static org.junit.jupiter.api.Assertions.assertNull;
15 import static org.junit.jupiter.api.Assertions.assertTrue;
16 import static org.mockito.Mockito.verify;
18 import com.google.common.collect.ImmutableList;
19 import java.util.List;
20 import javax.ws.rs.core.UriInfo;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Test;
25 import org.mockito.ArgumentCaptor;
26 import org.mockito.Captor;
27 import org.mockito.Mock;
28 import org.opendaylight.restconf.api.ApiPath;
29 import org.opendaylight.restconf.api.query.ContentParam;
30 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
31 import org.opendaylight.restconf.common.patch.PatchContext;
32 import org.opendaylight.restconf.common.patch.PatchEntity;
33 import org.opendaylight.restconf.nb.rfc8040.AbstractJukeboxTest;
34 import org.opendaylight.restconf.server.api.AbstractServerRequest;
35 import org.opendaylight.restconf.server.api.DataPatchResult;
36 import org.opendaylight.restconf.server.api.DataPostResult;
37 import org.opendaylight.restconf.server.api.DataPutResult;
38 import org.opendaylight.restconf.server.api.DataYangPatchResult;
39 import org.opendaylight.restconf.server.api.DatabindContext;
40 import org.opendaylight.restconf.server.api.PatchStatusContext;
41 import org.opendaylight.restconf.server.api.PatchStatusEntity;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.patch.rev170222.yang.patch.yang.patch.Edit.Operation;
43 import org.opendaylight.yangtools.yang.common.Empty;
44 import org.opendaylight.yangtools.yang.common.ErrorTag;
45 import org.opendaylight.yangtools.yang.common.ErrorType;
46 import org.opendaylight.yangtools.yang.common.QName;
47 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
48 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
49 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
50 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
51 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
52 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
53 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
54 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
55 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
56 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
57 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
58 import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
59 import org.opendaylight.yangtools.yang.data.api.schema.UserMapNode;
60 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
61 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
62 import org.w3c.dom.DOMException;
64 abstract class AbstractRestconfStrategyTest extends AbstractJukeboxTest {
65 static final ContainerNode JUKEBOX_WITH_BANDS = ImmutableNodes.newContainerBuilder()
66 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
67 .withChild(ImmutableNodes.newSystemMapBuilder()
68 .withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME))
69 .withChild(BAND_ENTRY)
70 .withChild(ImmutableNodes.newMapEntryBuilder()
71 .withNodeIdentifier(NodeIdentifierWithPredicates.of(PLAYLIST_QNAME, NAME_QNAME, "name of band 2"))
72 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "name of band 2"))
73 .withChild(ImmutableNodes.leafNode(DESCRIPTION_QNAME, "band description 2"))
77 static final ContainerNode JUKEBOX_WITH_PLAYLIST = ImmutableNodes.newContainerBuilder()
78 .withNodeIdentifier(new NodeIdentifier(JUKEBOX_QNAME))
79 .withChild(ImmutableNodes.newSystemMapBuilder()
80 .withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME))
81 .withChild(ImmutableNodes.newMapEntryBuilder()
82 .withNodeIdentifier(NodeIdentifierWithPredicates.of(PLAYLIST_QNAME, NAME_QNAME, "MyFavoriteBand-A"))
83 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "MyFavoriteBand-A"))
84 .withChild(ImmutableNodes.leafNode(DESCRIPTION_QNAME, "band description A"))
86 .withChild(ImmutableNodes.newMapEntryBuilder()
87 .withNodeIdentifier(NodeIdentifierWithPredicates.of(PLAYLIST_QNAME, NAME_QNAME, "MyFavoriteBand-B"))
88 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "MyFavoriteBand-B"))
89 .withChild(ImmutableNodes.leafNode(DESCRIPTION_QNAME, "band description B"))
93 static final MapNode PLAYLIST = ImmutableNodes.newSystemMapBuilder()
94 .withNodeIdentifier(new NodeIdentifier(PLAYLIST_QNAME))
95 .withChild(BAND_ENTRY)
97 // instance identifier for accessing container node "player"
98 static final YangInstanceIdentifier PLAYER_IID = YangInstanceIdentifier.of(JUKEBOX_QNAME, PLAYER_QNAME);
99 static final YangInstanceIdentifier ARTIST_IID = YangInstanceIdentifier.builder()
103 .nodeWithKey(ARTIST_QNAME, NAME_QNAME, "name of artist")
105 // FIXME: this looks weird
106 static final YangInstanceIdentifier CREATE_AND_DELETE_TARGET = GAP_IID.node(PLAYER_QNAME).node(GAP_QNAME);
109 static final QName BASE = QName.create("ns", "2016-02-28", "base");
110 private static final QName LIST_KEY_QNAME = QName.create(BASE, "list-key");
111 private static final QName LEAF_LIST_QNAME = QName.create(BASE, "leaf-list");
112 private static final QName LIST_QNAME = QName.create(BASE, "list");
113 static final QName CONT_QNAME = QName.create(BASE, "cont");
115 private static final NodeIdentifierWithPredicates NODE_WITH_KEY =
116 NodeIdentifierWithPredicates.of(LIST_QNAME, LIST_KEY_QNAME, "keyValue");
117 private static final NodeIdentifierWithPredicates NODE_WITH_KEY_2 =
118 NodeIdentifierWithPredicates.of(LIST_QNAME, LIST_KEY_QNAME, "keyValue2");
120 private static final LeafNode<?> CONTENT = ImmutableNodes.leafNode(QName.create(BASE, "leaf-content"), "content");
121 private static final LeafNode<?> CONTENT_2 =
122 ImmutableNodes.leafNode(QName.create(BASE, "leaf-content-different"), "content-different");
123 static final YangInstanceIdentifier PATH = YangInstanceIdentifier.builder()
128 static final YangInstanceIdentifier PATH_2 = YangInstanceIdentifier.builder()
131 .node(NODE_WITH_KEY_2)
133 static final YangInstanceIdentifier PATH_3 = YangInstanceIdentifier.of(CONT_QNAME, LIST_QNAME);
134 private static final MapEntryNode DATA = ImmutableNodes.newMapEntryBuilder()
135 .withNodeIdentifier(NODE_WITH_KEY)
138 static final MapEntryNode DATA_2 = ImmutableNodes.newMapEntryBuilder()
139 .withNodeIdentifier(NODE_WITH_KEY)
140 .withChild(CONTENT_2)
142 private static final LeafNode<?> CONTENT_LEAF = ImmutableNodes.leafNode(QName.create(BASE, "content"), "test");
143 private static final LeafNode<?> CONTENT_LEAF_2 = ImmutableNodes.leafNode(QName.create(BASE, "content2"), "test2");
144 static final ContainerNode DATA_3 = ImmutableNodes.newContainerBuilder()
145 .withNodeIdentifier(new NodeIdentifier(QName.create(BASE, "container")))
146 .withChild(CONTENT_LEAF)
148 static final ContainerNode DATA_4 = ImmutableNodes.newContainerBuilder()
149 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(QName.create(BASE, "container2")))
150 .withChild(CONTENT_LEAF_2)
152 static final MapNode LIST_DATA = ImmutableNodes.newSystemMapBuilder()
153 .withNodeIdentifier(new NodeIdentifier(QName.create(LIST_QNAME, "list")))
156 static final MapNode LIST_DATA_2 = ImmutableNodes.newSystemMapBuilder()
157 .withNodeIdentifier(new NodeIdentifier(QName.create(LIST_QNAME, "list")))
161 static final UserMapNode ORDERED_MAP_NODE_1 = ImmutableNodes.newUserMapBuilder()
162 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
165 static final UserMapNode ORDERED_MAP_NODE_2 = ImmutableNodes.newUserMapBuilder()
166 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
170 private static final MapEntryNode CHECK_DATA = ImmutableNodes.newMapEntryBuilder()
171 .withNodeIdentifier(NODE_WITH_KEY)
172 .withChild(CONTENT_2)
175 static final LeafSetNode<String> LEAF_SET_NODE_1 = ImmutableNodes.<String>newSystemLeafSetBuilder()
176 .withNodeIdentifier(new NodeIdentifier(LEAF_LIST_QNAME))
177 .withChildValue("one")
178 .withChildValue("two")
180 static final LeafSetNode<String> LEAF_SET_NODE_2 = ImmutableNodes.<String>newSystemLeafSetBuilder()
181 .withNodeIdentifier(new NodeIdentifier(LEAF_LIST_QNAME))
182 .withChildValue("three")
184 static final LeafSetNode<String> ORDERED_LEAF_SET_NODE_1 = ImmutableNodes.<String>newUserLeafSetBuilder()
185 .withNodeIdentifier(new NodeIdentifier(LEAF_LIST_QNAME))
186 .withChildValue("one")
187 .withChildValue("two")
189 static final LeafSetNode<String> ORDERED_LEAF_SET_NODE_2 = ImmutableNodes.<String>newUserLeafSetBuilder()
190 .withNodeIdentifier(new NodeIdentifier(LEAF_LIST_QNAME))
191 .withChildValue("three")
192 .withChildValue("four")
194 static final YangInstanceIdentifier LEAF_SET_NODE_PATH = YangInstanceIdentifier.builder()
196 .node(LEAF_LIST_QNAME)
198 private static final UnkeyedListEntryNode UNKEYED_LIST_ENTRY_NODE_1 = ImmutableNodes.newUnkeyedListEntryBuilder()
199 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
202 private static final UnkeyedListEntryNode UNKEYED_LIST_ENTRY_NODE_2 = ImmutableNodes.newUnkeyedListEntryBuilder()
203 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
204 .withChild(CONTENT_2)
206 static final UnkeyedListNode UNKEYED_LIST_NODE_1 = ImmutableNodes.newUnkeyedListBuilder()
207 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
208 .withChild(UNKEYED_LIST_ENTRY_NODE_1)
210 static final UnkeyedListNode UNKEYED_LIST_NODE_2 = ImmutableNodes.newUnkeyedListBuilder()
211 .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(LIST_QNAME))
212 .withChild(UNKEYED_LIST_ENTRY_NODE_2)
214 private static final NodeIdentifier NODE_IDENTIFIER =
215 new NodeIdentifier(QName.create("ns", "2016-02-28", "container"));
218 private EffectiveModelContext mockSchemaContext;
220 private UriInfo uriInfo;
222 private AbstractServerRequest<Empty> dataDeleteRequest;
224 private AbstractServerRequest<DataPatchResult> dataPatchRequest;
226 private ArgumentCaptor<DataPatchResult> dataPatchCaptor;
228 private AbstractServerRequest<DataPostResult> dataPostRequest;
230 private ArgumentCaptor<DataPostResult> dataPostCaptor;
232 private AbstractServerRequest<DataYangPatchResult> dataYangPatchRequest;
234 private ArgumentCaptor<DataYangPatchResult> dataYangPatchCaptor;
236 AbstractServerRequest<DataPutResult> dataPutRequest;
238 private DatabindContext mockDatabind;
241 void initMockDatabind() {
242 mockDatabind = DatabindContext.ofModel(mockSchemaContext);
245 abstract @NonNull RestconfStrategy newStrategy(DatabindContext databind);
247 final @NonNull RestconfStrategy jukeboxStrategy() {
248 return newStrategy(JUKEBOX_DATABIND);
251 final @NonNull RestconfStrategy mockStrategy() {
252 return newStrategy(mockDatabind);
256 * Test of successful DELETE operation.
259 final void testDeleteData() throws Exception {
260 testDeleteDataStrategy().dataDELETE(dataDeleteRequest, ApiPath.empty());
261 verify(dataDeleteRequest).completeWith(Empty.value());
264 abstract @NonNull RestconfStrategy testDeleteDataStrategy();
267 * Negative test for DELETE operation when data to delete does not exist. Error DATA_MISSING is expected.
270 final void testNegativeDeleteData() {
271 testNegativeDeleteDataStrategy().dataDELETE(dataDeleteRequest, ApiPath.empty());
273 final var captor = ArgumentCaptor.forClass(RestconfDocumentedException.class);
274 verify(dataDeleteRequest).completeWith(captor.capture());
276 final var errors = captor.getValue().getErrors();
277 assertEquals(1, errors.size());
278 final var error = errors.get(0);
279 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
280 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
283 abstract @NonNull RestconfStrategy testNegativeDeleteDataStrategy();
286 final void testPostContainerData() {
287 testPostContainerDataStrategy().postData(dataPostRequest, JUKEBOX_IID, EMPTY_JUKEBOX, null);
290 abstract @NonNull RestconfStrategy testPostContainerDataStrategy();
293 final void testPostListData() {
294 testPostListDataStrategy(BAND_ENTRY, PLAYLIST_IID.node(BAND_ENTRY.name()))
295 .postData(dataPostRequest, PLAYLIST_IID, PLAYLIST, null);
298 abstract @NonNull RestconfStrategy testPostListDataStrategy(MapEntryNode entryNode, YangInstanceIdentifier node);
301 final void testPostDataFail() {
302 final var domException = new DOMException((short) 414, "Post request failed");
303 testPostDataFailStrategy(domException).postData(dataPostRequest, JUKEBOX_IID, EMPTY_JUKEBOX, null);
305 final var captor = ArgumentCaptor.forClass(RestconfDocumentedException.class);
306 verify(dataPostRequest).completeWith(captor.capture());
308 final var errors = captor.getValue().getErrors();
309 assertEquals(1, errors.size());
310 assertThat(errors.get(0).getErrorInfo(), containsString(domException.getMessage()));
313 abstract @NonNull RestconfStrategy testPostDataFailStrategy(DOMException domException);
316 final void testPatchContainerData() {
317 testPatchContainerDataStrategy().merge(dataPatchRequest, JUKEBOX_IID, EMPTY_JUKEBOX);
318 verify(dataPatchRequest).completeWith(dataPatchCaptor.capture());
321 abstract @NonNull RestconfStrategy testPatchContainerDataStrategy();
324 final void testPatchLeafData() {
325 testPatchLeafDataStrategy().merge(dataPatchRequest, GAP_IID, GAP_LEAF);
326 verify(dataPatchRequest).completeWith(dataPatchCaptor.capture());
329 abstract @NonNull RestconfStrategy testPatchLeafDataStrategy();
332 final void testPatchListData() {
333 testPatchListDataStrategy().merge(dataPatchRequest, JUKEBOX_IID, JUKEBOX_WITH_PLAYLIST);
334 verify(dataPatchRequest).completeWith(dataPatchCaptor.capture());
337 abstract @NonNull RestconfStrategy testPatchListDataStrategy();
340 final void testPatchDataReplaceMergeAndRemove() {
341 final var buildArtistList = ImmutableNodes.newSystemMapBuilder()
342 .withNodeIdentifier(new NodeIdentifier(ARTIST_QNAME))
343 .withChild(ImmutableNodes.newMapEntryBuilder()
344 .withNodeIdentifier(NodeIdentifierWithPredicates.of(ARTIST_QNAME, NAME_QNAME, "name of artist"))
345 .withChild(ImmutableNodes.leafNode(NAME_QNAME, "name of artist"))
346 .withChild(ImmutableNodes.leafNode(DESCRIPTION_QNAME, "description of artist"))
350 patch(new PatchContext("patchRMRm",
351 List.of(new PatchEntity("edit1", Operation.Replace, ARTIST_IID, buildArtistList),
352 new PatchEntity("edit2", Operation.Merge, ARTIST_IID, buildArtistList),
353 new PatchEntity("edit3", Operation.Remove, ARTIST_IID))),
354 testPatchDataReplaceMergeAndRemoveStrategy(), false);
357 abstract @NonNull RestconfStrategy testPatchDataReplaceMergeAndRemoveStrategy();
360 final void testPatchDataCreateAndDelete() {
361 patch(new PatchContext("patchCD", List.of(
362 new PatchEntity("edit1", Operation.Create, PLAYER_IID, EMPTY_JUKEBOX),
363 new PatchEntity("edit2", Operation.Delete, CREATE_AND_DELETE_TARGET))),
364 testPatchDataCreateAndDeleteStrategy(), true);
367 abstract @NonNull RestconfStrategy testPatchDataCreateAndDeleteStrategy();
370 final void testPatchMergePutContainer() {
371 patch(new PatchContext("patchM", List.of(new PatchEntity("edit1", Operation.Merge, PLAYER_IID, EMPTY_JUKEBOX))),
372 testPatchMergePutContainerStrategy(), false);
375 abstract @NonNull RestconfStrategy testPatchMergePutContainerStrategy();
378 final void testDeleteNonexistentData() {
379 deleteNonexistentDataTestStrategy().patchData(dataYangPatchRequest,
380 new PatchContext("patchD", List.of(new PatchEntity("edit", Operation.Delete, CREATE_AND_DELETE_TARGET))));
382 verify(dataYangPatchRequest).completeWith(dataYangPatchCaptor.capture());
383 final var status = dataYangPatchCaptor.getValue().status();
384 assertEquals("patchD", status.patchId());
385 assertFalse(status.ok());
386 final var edits = status.editCollection();
387 assertEquals(1, edits.size());
388 final var edit = edits.get(0);
389 assertEquals("edit", edit.getEditId());
390 assertTestDeleteNonexistentData(status, edit);
393 abstract @NonNull RestconfStrategy deleteNonexistentDataTestStrategy();
395 abstract void assertTestDeleteNonexistentData(@NonNull PatchStatusContext status, @NonNull PatchStatusEntity edit);
398 final void readDataConfigTest() {
399 assertEquals(DATA_3, readData(ContentParam.CONFIG, PATH, readDataConfigTestStrategy()));
402 abstract @NonNull RestconfStrategy readDataConfigTestStrategy();
405 final void readAllHavingOnlyConfigTest() {
406 assertEquals(DATA_3, readData(ContentParam.ALL, PATH, readAllHavingOnlyConfigTestStrategy()));
409 abstract @NonNull RestconfStrategy readAllHavingOnlyConfigTestStrategy();
412 final void readAllHavingOnlyNonConfigTest() {
413 assertEquals(DATA_2, readData(ContentParam.ALL, PATH_2, readAllHavingOnlyNonConfigTestStrategy()));
416 abstract @NonNull RestconfStrategy readAllHavingOnlyNonConfigTestStrategy();
419 final void readDataNonConfigTest() {
420 assertEquals(DATA_2, readData(ContentParam.NONCONFIG, PATH_2, readDataNonConfigTestStrategy()));
423 abstract @NonNull RestconfStrategy readDataNonConfigTestStrategy();
426 final void readContainerDataAllTest() {
427 assertEquals(ImmutableNodes.newContainerBuilder()
428 .withNodeIdentifier(NODE_IDENTIFIER)
429 .withChild(CONTENT_LEAF)
430 .withChild(CONTENT_LEAF_2)
431 .build(), readData(ContentParam.ALL, PATH, readContainerDataAllTestStrategy()));
434 abstract @NonNull RestconfStrategy readContainerDataAllTestStrategy();
437 final void readContainerDataConfigNoValueOfContentTest() {
438 assertEquals(ImmutableNodes.newContainerBuilder()
439 .withNodeIdentifier(NODE_IDENTIFIER)
440 .withChild(CONTENT_LEAF)
441 .withChild(CONTENT_LEAF_2)
442 .build(), readData(ContentParam.ALL, PATH, readContainerDataConfigNoValueOfContentTestStrategy()));
445 abstract @NonNull RestconfStrategy readContainerDataConfigNoValueOfContentTestStrategy();
448 final void readListDataAllTest() {
449 assertEquals(ImmutableNodes.newSystemMapBuilder()
450 .withNodeIdentifier(new NodeIdentifier(QName.create("ns", "2016-02-28", "list")))
451 .withChild(CHECK_DATA)
452 .build(), readData(ContentParam.ALL, PATH_3, readListDataAllTestStrategy()));
455 abstract @NonNull RestconfStrategy readListDataAllTestStrategy();
458 final void readOrderedListDataAllTest() {
459 assertEquals(ImmutableNodes.newUserMapBuilder()
460 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
461 .withChild(CHECK_DATA)
462 .build(), readData(ContentParam.ALL, PATH_3, readOrderedListDataAllTestStrategy()));
465 abstract @NonNull RestconfStrategy readOrderedListDataAllTestStrategy();
468 void readUnkeyedListDataAllTest() {
469 assertEquals(ImmutableNodes.newUnkeyedListBuilder()
470 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
471 .withChild(ImmutableNodes.newUnkeyedListEntryBuilder()
472 .withNodeIdentifier(new NodeIdentifier(LIST_QNAME))
473 .withChild(UNKEYED_LIST_ENTRY_NODE_1.body().iterator().next())
474 .withChild(UNKEYED_LIST_ENTRY_NODE_2.body().iterator().next())
476 .build(), readData(ContentParam.ALL, PATH_3, readUnkeyedListDataAllTestStrategy()));
479 abstract @NonNull RestconfStrategy readUnkeyedListDataAllTestStrategy();
482 final void readLeafListDataAllTest() {
483 assertEquals(ImmutableNodes.<String>newSystemLeafSetBuilder()
484 .withNodeIdentifier(new NodeIdentifier(LEAF_LIST_QNAME))
485 .withValue(ImmutableList.<LeafSetEntryNode<String>>builder()
486 .addAll(LEAF_SET_NODE_1.body())
487 .addAll(LEAF_SET_NODE_2.body())
489 .build(), readData(ContentParam.ALL, LEAF_SET_NODE_PATH, readLeafListDataAllTestStrategy()));
492 abstract @NonNull RestconfStrategy readLeafListDataAllTestStrategy();
495 final void readOrderedLeafListDataAllTest() {
496 assertEquals(ImmutableNodes.<String>newUserLeafSetBuilder()
497 .withNodeIdentifier(new NodeIdentifier(LEAF_LIST_QNAME))
498 .withValue(ImmutableList.<LeafSetEntryNode<String>>builder()
499 .addAll(ORDERED_LEAF_SET_NODE_1.body())
500 .addAll(ORDERED_LEAF_SET_NODE_2.body())
502 .build(), readData(ContentParam.ALL, LEAF_SET_NODE_PATH, readOrderedLeafListDataAllTestStrategy()));
505 abstract @NonNull RestconfStrategy readOrderedLeafListDataAllTestStrategy();
508 void readDataWrongPathOrNoContentTest() {
509 assertNull(readData(ContentParam.CONFIG, PATH_2, readDataWrongPathOrNoContentTestStrategy()));
512 abstract @NonNull RestconfStrategy readDataWrongPathOrNoContentTestStrategy();
515 * Read specific type of data from data store via transaction.
517 * @param content type of data to read (config, state, all)
518 * @param strategy {@link RestconfStrategy} - wrapper for variables
519 * @return {@link NormalizedNode}
521 private static @Nullable NormalizedNode readData(final @NonNull ContentParam content,
522 final YangInstanceIdentifier path, final @NonNull RestconfStrategy strategy) {
523 return strategy.readData(content, path, null);
526 private void patch(final PatchContext patchContext, final RestconfStrategy strategy, final boolean failed) {
527 strategy.patchData(dataYangPatchRequest, patchContext);
528 verify(dataYangPatchRequest).completeWith(dataYangPatchCaptor.capture());
529 final var patchStatusContext = dataYangPatchCaptor.getValue().status();
531 for (var entity : patchStatusContext.editCollection()) {
533 assertTrue(entity.isOk(), "Edit " + entity.getEditId() + " failed");
535 assertTrue(entity.isOk());
538 assertTrue(patchStatusContext.ok());