6c0ba762e043fb0abc62a7c2c48f39e5c9f96763
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / utils / PlainPatchDataTransactionUtilTest.java
1 /*
2  * Copyright (c) 2020 Lumina Networks, Inc. and others. All rights reserved.
3  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
4  *
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
8  */
9 package org.opendaylight.restconf.nb.rfc8040.rests.utils;
10
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;
15
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;
47
48 public class PlainPatchDataTransactionUtilTest {
49
50     private static final String PATH_FOR_NEW_SCHEMA_CONTEXT = "/jukebox";
51
52     @Mock
53     private DOMTransactionChain transactionChain;
54     @Mock
55     private DOMDataTreeReadWriteTransaction readWrite;
56     @Mock
57     private DOMDataTreeReadTransaction read;
58     @Mock
59     private DOMDataTreeWriteTransaction write;
60     @Mock
61     private DOMDataBroker mockDataBroker;
62
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;
73
74     @Before
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();
80
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");
86
87         final NodeIdentifierWithPredicates nidBandA =
88                 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-A");
89         final NodeIdentifierWithPredicates nidBandB =
90                 NodeIdentifierWithPredicates.of(qnPlaylist, qnPlaylistKey, "MyFavoriteBand-B");
91
92         this.iidGap = YangInstanceIdentifier.builder()
93                 .node(qnJukebox)
94                 .node(qnPlayer)
95                 .node(qnGap)
96                 .build();
97         this.schemaNodeForGap = DataSchemaContextTree.from(this.schema).getChild(this.iidGap).getDataSchemaNode();
98
99         this.iidJukebox = YangInstanceIdentifier.builder()
100                 .node(qnJukebox)
101                 .build();
102         this.schemaNodeForJukebox = DataSchemaContextTree.from(this.schema)
103                 .getChild(this.iidJukebox).getDataSchemaNode();
104
105         this.leafGap = Builders.leafBuilder()
106                 .withNodeIdentifier(new NodeIdentifier(qnGap))
107                 .withValue(0.2)
108                 .build();
109         final ContainerNode playerContainer = Builders.containerBuilder()
110                 .withNodeIdentifier(new NodeIdentifier(qnPlayer))
111                 .withChild(this.leafGap)
112                 .build();
113         this.jukeboxContainerWithPlayer = Builders.containerBuilder()
114                 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
115                 .withChild(playerContainer)
116                 .build();
117
118         // ----------
119
120         final LeafNode<Object> leafBandA = Builders.leafBuilder()
121                 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
122                 .withValue("MyFavoriteBand-A")
123                 .build();
124         final LeafNode<Object> leafDescriptionA = Builders.leafBuilder()
125                 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
126                 .withValue("band description A")
127                 .build();
128         final MapEntryNode entryBandA = Builders.mapEntryBuilder()
129                 .withNodeIdentifier(nidBandA)
130                 .withChild(leafBandA)
131                 .withChild(leafDescriptionA)
132                 .build();
133
134         final LeafNode<Object> leafBandB = Builders.leafBuilder()
135                 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "name")))
136                 .withValue("MyFavoriteBand-B")
137                 .build();
138         final LeafNode<Object> leafDescriptionB = Builders.leafBuilder()
139                 .withNodeIdentifier(new NodeIdentifier(QName.create(qnJukebox, "description")))
140                 .withValue("band description B")
141                 .build();
142         final MapEntryNode entryBandB = Builders.mapEntryBuilder()
143                 .withNodeIdentifier(nidBandB)
144                 .withChild(leafBandB)
145                 .withChild(leafDescriptionB)
146                 .build();
147
148         final MapNode listBands = Builders.mapBuilder()
149                 .withNodeIdentifier(new NodeIdentifier(qnPlaylist))
150                 .withChild(entryBandA)
151                 .withChild(entryBandB)
152                 .build();
153         this.jukeboxContainerWithPlaylist = Builders.containerBuilder()
154                 .withNodeIdentifier(new NodeIdentifier(qnJukebox))
155                 .withChild(listBands)
156                 .build();
157
158         Mockito.doReturn(transactionChain).when(mockDataBroker).createTransactionChain(Mockito.any());
159         transactionChainHandler = new TransactionChainHandler(mockDataBroker);
160     }
161
162     @Test
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);
167
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();
176
177         PlainPatchDataTransactionUtil.patchData(payload,
178                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
179                 this.refSchemaCtx);
180
181         verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
182                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
183     }
184
185     @Test
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);
190
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();
199
200         PlainPatchDataTransactionUtil.patchData(payload,
201                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
202                 this.refSchemaCtx);
203
204         verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION,
205                 payload.getInstanceIdentifierContext().getInstanceIdentifier(), payload.getData());
206     }
207
208     @Test
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);
213
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();
222
223         PlainPatchDataTransactionUtil.patchData(payload,
224                 new TransactionVarsWrapper(payload.getInstanceIdentifierContext(), null, transactionChainHandler),
225                 this.refSchemaCtx);
226
227         verify(this.readWrite).merge(LogicalDatastoreType.CONFIGURATION, this.iidJukebox, payload.getData());
228     }
229 }