2 * Copyright (c) 2020 Lumina Networks, Inc. and others. All rights reserved.
3 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
5 * This program and the accompanying materials are made available under the
6 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
11 import static org.mockito.Mockito.doNothing;
12 import static org.mockito.Mockito.doReturn;
13 import static org.mockito.Mockito.verify;
14 import static org.opendaylight.yangtools.util.concurrent.FluentFutures.immediateFalseFluentFuture;
16 import java.util.Optional;
17 import org.junit.Before;
18 import org.junit.Test;
19 import org.mockito.Mock;
20 import org.mockito.Mockito;
21 import org.mockito.MockitoAnnotations;
22 import org.opendaylight.mdsal.common.api.CommitInfo;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
27 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
28 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
29 import org.opendaylight.netconf.dom.api.NetconfDataTreeService;
30 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
31 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
32 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
33 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
34 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.MdsalRestconfStrategy;
35 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.NetconfRestconfStrategy;
36 import org.opendaylight.yangtools.yang.common.QName;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
40 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
44 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
45 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
46 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
48 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
50 public class PlainPatchDataTransactionUtilTest {
51 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
53 private DOMTransactionChain transactionChain;
55 private DOMDataTreeReadWriteTransaction readWrite;
57 private DOMDataTreeReadTransaction read;
59 private DOMDataTreeWriteTransaction write;
61 private DOMDataBroker mockDataBroker;
63 private NetconfDataTreeService netconfService;
65 private TransactionChainHandler transactionChainHandler;
66 private LeafNode<?> leafGap;
67 private ContainerNode jukeboxContainerWithPlayer;
68 private ContainerNode jukeboxContainerWithPlaylist;
69 private EffectiveModelContext schema;
70 private DataSchemaNode schemaNodeForGap;
71 private YangInstanceIdentifier iidGap;
72 private DataSchemaNode schemaNodeForJukebox;
73 private YangInstanceIdentifier iidJukebox;
76 public void setUp() throws Exception {
77 MockitoAnnotations.initMocks(this);
78 this.schema = YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT));
80 final QName qnJukebox = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
81 final QName qnPlayer = QName.create(qnJukebox, "player");
82 final QName qnGap = QName.create(qnJukebox, "gap");
83 final QName qnPlaylist = QName.create(qnJukebox, "playlist");
84 final QName qnPlaylistKey = QName.create(qnJukebox, "name");
86 final NodeIdentifierWithPredicates nidBandA =
87 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-A");
88 final NodeIdentifierWithPredicates nidBandB =
89 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-B");
91 this.iidGap = YangInstanceIdentifier.builder()
96 this.schemaNodeForGap = DataSchemaContextTree.from(this.schema).getChild(this.iidGap).getDataSchemaNode();
98 this.iidJukebox = YangInstanceIdentifier.builder()
101 this.schemaNodeForJukebox = DataSchemaContextTree.from(this.schema)
102 .getChild(this.iidJukebox).getDataSchemaNode();
104 this.leafGap = Builders.leafBuilder()
105 .withNodeIdentifier(new NodeIdentifier(qnGap))
108 final ContainerNode playerContainer = Builders.containerBuilder()
109 .withNodeIdentifier(new NodeIdentifier(qnPlayer))
110 .withChild(this.leafGap)
112 this.jukeboxContainerWithPlayer = Builders.containerBuilder()
113 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
114 .withChild(playerContainer)
119 final LeafNode<Object> leafBandA = Builders.leafBuilder()
120 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
121 .withValue("MyFavoriteBand-A")
123 final LeafNode<Object> leafDescriptionA = Builders.leafBuilder()
124 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
125 .withValue("band description A")
127 final MapEntryNode entryBandA = Builders.mapEntryBuilder()
128 .withNodeIdentifier(nidBandA)
129 .withChild(leafBandA)
130 .withChild(leafDescriptionA)
133 final LeafNode<Object> leafBandB = Builders.leafBuilder()
134 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
135 .withValue("MyFavoriteBand-B")
137 final LeafNode<Object> leafDescriptionB = Builders.leafBuilder()
138 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
139 .withValue("band description B")
141 final MapEntryNode entryBandB = Builders.mapEntryBuilder()
142 .withNodeIdentifier(nidBandB)
143 .withChild(leafBandB)
144 .withChild(leafDescriptionB)
147 final MapNode listBands = Builders.mapBuilder()
148 .withNodeIdentifier(new NodeIdentifier(qnPlaylist))
149 .withChild(entryBandA)
150 .withChild(entryBandB)
152 this.jukeboxContainerWithPlaylist = Builders.containerBuilder()
153 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
154 .withChild(listBands)
157 Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
158 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
162 public void testPatchContainerData() {
163 final InstanceIdentifierContext<DataSchemaNode> iidContext =
164 new InstanceIdentifierContext<>(this.iidJukebox, this.schemaNodeForJukebox, null, this.schema);
165 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.jukeboxContainerWithPlayer);
167 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
168 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
169 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
170 doReturn(immediateFalseFluentFuture())
171 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidJukebox);
172 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
173 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
174 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
175 doReturn(CommitInfo.emptyFluentFuture()).when(this.netconfService).commit(Mockito.any());
177 PlainPatchDataTransactionUtil.patchData(payload,
178 new MdsalRestconfStrategy(iidContext, transactionChainHandler),
180 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
181 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
183 PlainPatchDataTransactionUtil.patchData(payload,
184 new NetconfRestconfStrategy(netconfService, iidContext),
186 verify(this.netconfService).merge(LogicalDatastoreType.CONFIGURATION,
187 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData(), Optional.empty());
191 public void testPatchLeafData() {
192 final InstanceIdentifierContext<DataSchemaNode> iidContext =
193 new InstanceIdentifierContext<>(this.iidGap, this.schemaNodeForGap, null, this.schema);
194 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.leafGap);
196 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
197 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
198 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
199 doReturn(immediateFalseFluentFuture())
200 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidGap);
201 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
202 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
203 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
204 doReturn(CommitInfo.emptyFluentFuture()).when(this.netconfService).commit(Mockito.any());
206 PlainPatchDataTransactionUtil.patchData(payload, new MdsalRestconfStrategy(iidContext, transactionChainHandler),
208 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
209 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
211 PlainPatchDataTransactionUtil.patchData(payload, new NetconfRestconfStrategy(netconfService, iidContext),
213 verify(this.netconfService).merge(LogicalDatastoreType.CONFIGURATION,
214 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData(), Optional.empty());
218 public void testPatchListData() {
219 final InstanceIdentifierContext<DataSchemaNode> iidContext =
220 new InstanceIdentifierContext<>(this.iidJukebox, this.schemaNodeForJukebox, null, this.schema);
221 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.jukeboxContainerWithPlaylist);
223 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
224 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
225 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
226 doReturn(immediateFalseFluentFuture())
227 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidJukebox);
228 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
229 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
230 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
231 doReturn(CommitInfo.emptyFluentFuture()).when(this.netconfService).commit(Mockito.any());
233 PlainPatchDataTransactionUtil.patchData(payload,
234 new MdsalRestconfStrategy(iidContext, transactionChainHandler),
236 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION, this.iidJukebox, payload.getData());
238 PlainPatchDataTransactionUtil.patchData(payload, new NetconfRestconfStrategy(netconfService, iidContext),
240 verify(this.netconfService).merge(LogicalDatastoreType.CONFIGURATION, this.iidJukebox, payload.getData(),