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.rests.transactions.TransactionVarsWrapper;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
35 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
36 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
37 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
38 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
39 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
41 import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
42 import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
43 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
44 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
45 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
47 public class PlainPatchDataTransactionUtilTest {
49 private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
52 private DOMTransactionChain transactionChain;
54 private DOMDataTreeReadWriteTransaction readWrite;
56 private DOMDataTreeReadTransaction read;
58 private DOMDataTreeWriteTransaction write;
60 private DOMDataBroker mockDataBroker;
62 private TransactionChainHandler transactionChainHandler;
63 private LeafNode leafGap;
64 private ContainerNode jukeboxContainerWithPlayer;
65 private ContainerNode jukeboxContainerWithPlaylist;
66 private EffectiveModelContext schema;
67 private DataSchemaNode schemaNodeForGap;
68 private YangInstanceIdentifier iidGap;
69 private DataSchemaNode schemaNodeForJukebox;
70 private YangInstanceIdentifier iidJukebox;
73 public void setUp() throws Exception {
74 MockitoAnnotations.initMocks(this);
75 this.schema = YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles(PATH_FOR_NEW_SCHEMA_CONTEXT));
77 final QName qnJukebox = QName.create("http://example.com/ns/example-jukebox", "2015-04-04", "jukebox");
78 final QName qnPlayer = QName.create(qnJukebox, "player");
79 final QName qnGap = QName.create(qnJukebox, "gap");
80 final QName qnPlaylist = QName.create(qnJukebox, "playlist");
81 final QName qnPlaylistKey = QName.create(qnJukebox, "name");
83 final NodeIdentifierWithPredicates nidBandA =
84 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-A");
85 final NodeIdentifierWithPredicates nidBandB =
86 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-B");
88 this.iidGap = YangInstanceIdentifier.builder()
93 this.schemaNodeForGap = DataSchemaContextTree.from(this.schema).getChild(this.iidGap).getDataSchemaNode();
95 this.iidJukebox = YangInstanceIdentifier.builder()
98 this.schemaNodeForJukebox = DataSchemaContextTree.from(this.schema)
99 .getChild(this.iidJukebox).getDataSchemaNode();
101 this.leafGap = Builders.leafBuilder()
102 .withNodeIdentifier(new NodeIdentifier(qnGap))
105 final ContainerNode playerContainer = Builders.containerBuilder()
106 .withNodeIdentifier(new NodeIdentifier(qnPlayer))
107 .withChild(this.leafGap)
109 this.jukeboxContainerWithPlayer = Builders.containerBuilder()
110 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
111 .withChild(playerContainer)
116 final LeafNode<Object> leafBandA = Builders.leafBuilder()
117 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
118 .withValue("MyFavoriteBand-A")
120 final LeafNode<Object> leafDescriptionA = Builders.leafBuilder()
121 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
122 .withValue("band description A")
124 final MapEntryNode entryBandA = Builders.mapEntryBuilder()
125 .withNodeIdentifier(nidBandA)
126 .withChild(leafBandA)
127 .withChild(leafDescriptionA)
130 final LeafNode<Object> leafBandB = Builders.leafBuilder()
131 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
132 .withValue("MyFavoriteBand-B")
134 final LeafNode<Object> leafDescriptionB = Builders.leafBuilder()
135 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
136 .withValue("band description B")
138 final MapEntryNode entryBandB = Builders.mapEntryBuilder()
139 .withNodeIdentifier(nidBandB)
140 .withChild(leafBandB)
141 .withChild(leafDescriptionB)
144 final MapNode listBands = Builders.mapBuilder()
145 .withNodeIdentifier(new NodeIdentifier(qnPlaylist))
146 .withChild(entryBandA)
147 .withChild(entryBandB)
149 this.jukeboxContainerWithPlaylist = Builders.containerBuilder()
150 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
151 .withChild(listBands)
154 Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
155 transactionChainHandler = new TransactionChainHandler(mockDataBroker);
159 public void testPatchContainerData() {
160 final InstanceIdentifierContext<DataSchemaNode> iidContext =
161 new InstanceIdentifierContext<>(this.iidJukebox, this.schemaNodeForJukebox, null, this.schema);
162 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.jukeboxContainerWithPlayer);
164 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
165 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
166 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
167 doReturn(immediateFalseFluentFuture())
168 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidJukebox);
169 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
170 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
171 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
173 PlainPatchDataTransactionUtil.patchData(payload,
174 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
177 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
178 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
182 public void testPatchLeafData() {
183 final InstanceIdentifierContext<DataSchemaNode> iidContext =
184 new InstanceIdentifierContext<>(this.iidGap, this.schemaNodeForGap, null, this.schema);
185 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.leafGap);
187 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
188 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
189 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
190 doReturn(immediateFalseFluentFuture())
191 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidGap);
192 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
193 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
194 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
196 PlainPatchDataTransactionUtil.patchData(payload,
197 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
200 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
201 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
205 public void testPatchListData() {
206 final InstanceIdentifierContext<DataSchemaNode> iidContext =
207 new InstanceIdentifierContext<>(this.iidJukebox, this.schemaNodeForJukebox, null, this.schema);
208 final NormalizedNodeContext payload = new NormalizedNodeContext(iidContext, this.jukeboxContainerWithPlaylist);
210 doReturn(this.readWrite).when(this.transactionChain).newReadWriteTransaction();
211 doReturn(this.read).when(this.transactionChain).newReadOnlyTransaction();
212 doReturn(this.write).when(this.transactionChain).newWriteOnlyTransaction();
213 doReturn(immediateFalseFluentFuture())
214 .when(this.readWrite).exists(LogicalDatastoreType.CONFIGURATION, this.iidJukebox);
215 doNothing().when(this.readWrite).put(LogicalDatastoreType.CONFIGURATION,
216 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
217 doReturn(CommitInfo.emptyFluentFuture()).when(this.readWrite).commit();
219 PlainPatchDataTransactionUtil.patchData(payload,
220 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
223 verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION, this.iidJukebox, payload.getData());