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 org.junit.Before;
17 import org.junit.Test;
18 import org.mockito.Mock;
19 import org.mockito.Mockito;
20 import org.mockito.MockitoAnnotations;
21 import org.opendaylight.mdsal.common.api.CommitInfo;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
27 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
28 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
29 import org.opendaylight.restconf.common.context.NormalizedNodeContext;
30 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
31 import org.opendaylight.restconf.nb.rfc8040.handlers.TransactionChainHandler;
32 import org.opendaylight.restconf.nb.rfc8040.references.SchemaContextRef;
33 import org.opendaylight.restconf.nb.rfc8040.rests.transactions.TransactionVarsWrapper;
34 import org.opendaylight.yangtools.yang.common.QName;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
38 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
42 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
43 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
44 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
45 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
46 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
48 public class PlainPatchDataTransactionUtilTest {
50 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 TransactionChainHandler transactionChainHandler;
64 private SchemaContextRef refSchemaCtx;
65 private LeafNode leafGap;
66 private ContainerNode jukeboxContainerWithPlayer;
67 private ContainerNode jukeboxContainerWithPlaylist;
68 private SchemaContext schema;
69 private DataSchemaNode schemaNodeForGap;
70 private YangInstanceIdentifier iidGap;
71 private DataSchemaNode schemaNodeForJukebox;
72 private YangInstanceIdentifier iidJukebox;
75 public void setUp() throws Exception {
76 MockitoAnnotations.initMocks(this);
77 this.refSchemaCtx = new SchemaContextRef(
78 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT)));
79 this.schema = this.refSchemaCtx.get();
81 final QName qnJukebox = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
82 final QName qnPlayer = QName.create(qnJukebox, "player");
83 final QName qnGap = QName.create(qnJukebox, "gap");
84 final QName qnPlaylist = QName.create(qnJukebox, "playlist");
85 final QName qnPlaylistKey = QName.create(qnJukebox, "name");
87 final NodeIdentifierWithPredicates nidBandA =
88 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-A");
89 final NodeIdentifierWithPredicates nidBandB =
90 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-B");
92 this.iidGap = YangInstanceIdentifier.builder()
97 this.schemaNodeForGap = DataSchemaContextTree.from(this.schema).getChild(this.iidGap).getDataSchemaNode();
99 this.iidJukebox = YangInstanceIdentifier.builder()
102 this.schemaNodeForJukebox = DataSchemaContextTree.from(this.schema)
103 .getChild(this.iidJukebox).getDataSchemaNode();
105 this.leafGap = Builders.leafBuilder()
106 .withNodeIdentifier(new NodeIdentifier(qnGap))
109 final ContainerNode playerContainer = Builders.containerBuilder()
110 .withNodeIdentifier(new NodeIdentifier(qnPlayer))
111 .withChild(this.leafGap)
113 this.jukeboxContainerWithPlayer = Builders.containerBuilder()
114 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
115 .withChild(playerContainer)
120 final LeafNode<Object> leafBandA = Builders.leafBuilder()
121 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
122 .withValue("MyFavoriteBand-A")
124 final LeafNode<Object> leafDescriptionA = Builders.leafBuilder()
125 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
126 .withValue("band description A")
128 final MapEntryNode entryBandA = Builders.mapEntryBuilder()
129 .withNodeIdentifier(nidBandA)
130 .withChild(leafBandA)
131 .withChild(leafDescriptionA)
134 final LeafNode<Object> leafBandB = Builders.leafBuilder()
135 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
136 .withValue("MyFavoriteBand-B")
138 final LeafNode<Object> leafDescriptionB = Builders.leafBuilder()
139 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
140 .withValue("band description B")
142 final MapEntryNode entryBandB = Builders.mapEntryBuilder()
143 .withNodeIdentifier(nidBandB)
144 .withChild(leafBandB)
145 .withChild(leafDescriptionB)
148 final MapNode listBands = Builders.mapBuilder()
149 .withNodeIdentifier(new NodeIdentifier(qnPlaylist))
150 .withChild(entryBandA)
151 .withChild(entryBandB)
153 this.jukeboxContainerWithPlaylist = Builders.containerBuilder()
154 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
155 .withChild(listBands)
158 Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
159 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
163 public void testPatchContainerData() {
164 final InstanceIdentifierContext<DataSchemaNode> iidContext =
165 new InstanceIdentifierContext<>(this.iidJukebox, this.schemaNodeForJukebox, null, this.schema);
166 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.jukeboxContainerWithPlayer);
168 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
169 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
170 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
171 doReturn(immediateFalseFluentFuture())
172 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidJukebox);
173 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
174 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
175 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
177 PlainPatchDataTransactionUtil.patchData(payload,
178 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
181 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
182 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
186 public void testPatchLeafData() {
187 final InstanceIdentifierContext<DataSchemaNode> iidContext =
188 new InstanceIdentifierContext<>(this.iidGap, this.schemaNodeForGap, null, this.schema);
189 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.leafGap);
191 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
192 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
193 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
194 doReturn(immediateFalseFluentFuture())
195 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidGap);
196 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
197 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
198 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
200 PlainPatchDataTransactionUtil.patchData(payload,
201 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
204 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
205 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
209 public void testPatchListData() {
210 final InstanceIdentifierContext<DataSchemaNode> iidContext =
211 new InstanceIdentifierContext<>(this.iidJukebox, this.schemaNodeForJukebox, null, this.schema);
212 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.jukeboxContainerWithPlaylist);
214 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
215 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
216 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
217 doReturn(immediateFalseFluentFuture())
218 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidJukebox);
219 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
220 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
221 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
223 PlainPatchDataTransactionUtil.patchData(payload,
224 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
227 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION, this.iidJukebox, payload.getData());