Add ImmutableNode.newXYXBuilder() methods
[yangtools.git] / data / yang-data-tree-ri / src / test / java / org / opendaylight / yangtools / yang / data / tree / leafref / DataTreeCandidateValidatorTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.tree.leafref;
9
10 import static org.junit.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
12
13 import java.util.HashMap;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.junit.jupiter.api.AfterAll;
16 import org.junit.jupiter.api.BeforeAll;
17 import org.junit.jupiter.api.Test;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.common.QNameModule;
20 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
21 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
22 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
23 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
24 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
25 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
26 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
27 import org.opendaylight.yangtools.yang.data.api.schema.SystemMapNode;
28 import org.opendaylight.yangtools.yang.data.spi.node.ImmutableNodes;
29 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
30 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
31 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
32 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
33 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
34 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
35 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.Module;
37 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 public class DataTreeCandidateValidatorTest {
42
43     private static EffectiveModelContext context;
44     private static Module valModule;
45     private static QNameModule valModuleQname;
46     private static LeafRefContext rootLeafRefContext;
47     public static DataTree inMemoryDataTree;
48
49     private static QName odl;
50     private static QName project;
51     private static QName name;
52     private static QName desc;
53     private static QName lead;
54     private static QName owner;
55     private static QName odlContributor;
56     private static QName contributor;
57     private static QName odlProjectName;
58     private static QName odlProjectDesc;
59     private static QName login;
60     private static QName contributorName;
61     private static QName l1;
62     private static QName l2;
63     private static QName con1;
64     private static QName ch1;
65     private static QName ch2;
66     private static QName leafrefInChoice;
67     private static QName listInChoice;
68
69     private static QName leafrefInChoiceToChoice;
70     private static QName con3;
71     private static QName list3InChoice;
72     private static QName l3;
73     private static QName choiceInCon3;
74
75     private static QName listInChoiceKey;
76     private static QName k;
77
78     private static QName leafrefLeafList;
79
80     private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateValidatorTest.class);
81     private static final String NEW_LINE = System.getProperty("line.separator");
82
83     @BeforeAll
84     static void init() throws DataValidationFailedException {
85         context = YangParserTestUtils.parseYangResourceDirectory("/leafref-validation");
86
87         for (final var module : context.getModules()) {
88             if (module.getName().equals("leafref-validation")) {
89                 valModule = module;
90             }
91         }
92
93         valModuleQname = valModule.getQNameModule();
94         rootLeafRefContext = LeafRefContext.create(context);
95
96         odl = QName.create(valModuleQname, "odl-project");
97         project = QName.create(valModuleQname, "project");
98         name = QName.create(valModuleQname, "name");
99         desc = QName.create(valModuleQname, "desc");
100         lead = QName.create(valModuleQname, "project-lead");
101         owner = QName.create(valModuleQname, "project-owner");
102
103         odlContributor = QName.create(valModuleQname, "odl-contributor");
104         contributor = QName.create(valModuleQname, "contributor");
105         odlProjectName = QName.create(valModuleQname, "odl-project-name");
106         login = QName.create(valModuleQname, "login");
107         contributorName = QName.create(valModuleQname, "contributor-name");
108
109         con1 = QName.create(valModuleQname, "con1");
110         l1 = QName.create(valModuleQname, "l1");
111         l2 = QName.create(valModuleQname, "l2");
112         odlProjectDesc = QName.create(valModuleQname, "odl-project-desc");
113
114         ch1 = QName.create(valModuleQname, "ch1");
115         ch2 = QName.create(valModuleQname, "ch2");
116         leafrefInChoice = QName.create(valModuleQname, "leafref-in-choice");
117         listInChoice = QName.create(valModuleQname, "list-in-choice");
118
119         leafrefInChoiceToChoice = QName.create(valModuleQname, "leafref-in-choice-to-choice");
120         con3 = QName.create(valModuleQname, "con3");
121         list3InChoice = QName.create(valModuleQname, "list3-in-choice");
122         l3 = QName.create(valModuleQname, "l3");
123         choiceInCon3 = QName.create(valModuleQname, "choice-in-con3");
124
125         listInChoiceKey = QName.create(valModuleQname, "list-in-choice-key");
126         k = QName.create(valModuleQname, "k");
127
128         leafrefLeafList = QName.create(valModuleQname, "leafref-leaf-list");
129
130         inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL, context);
131
132         final var initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
133
134         final var odlProjectContainer = createOdlContainer();
135
136         final var path = YangInstanceIdentifier.of(odl);
137         initialDataTreeModification.write(path, odlProjectContainer);
138         initialDataTreeModification.ready();
139
140         final var writeContributorsCandidate = inMemoryDataTree
141                 .prepare(initialDataTreeModification);
142         inMemoryDataTree.commit(writeContributorsCandidate);
143     }
144
145     @AfterAll
146     static void cleanup() {
147         inMemoryDataTree = null;
148         rootLeafRefContext = null;
149         valModule = null;
150         context = null;
151     }
152
153     @Test
154     void dataTreeCanditateValidationTest() throws DataValidationFailedException {
155         write();
156
157         write2();
158
159         delete();
160
161         writeContributors();
162
163         writeMapEntry();
164
165         writeIntoMapEntry();
166     }
167
168     private static void writeContributors() throws DataValidationFailedException {
169
170         final var contributorContainer = createBasicContributorContainer();
171
172         final var contributorPath = YangInstanceIdentifier.of(odlContributor);
173         final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
174         writeModification.write(contributorPath, contributorContainer);
175         writeModification.ready();
176
177         final var writeContributorsCandidate = inMemoryDataTree
178                 .prepare(writeModification);
179
180         LOG.debug("*************************");
181         LOG.debug("Before write of contributors: ");
182         LOG.debug("*************************");
183         LOG.debug(inMemoryDataTree.toString());
184
185         final var ex = assertThrows(LeafRefDataValidationFailedException.class,
186             () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
187         assertEquals(3, ex.getValidationsErrorsCount());
188
189         inMemoryDataTree.commit(writeContributorsCandidate);
190
191         LOG.debug("*************************");
192         LOG.debug("After write of contributors: ");
193         LOG.debug("*************************");
194         LOG.debug(inMemoryDataTree.toString());
195     }
196
197     private static void writeIntoMapEntry() throws DataValidationFailedException {
198         final var keys = new HashMap<QName, Object>();
199         keys.put(name, "New Project");
200         final var mapEntryPath = NodeIdentifierWithPredicates.of(project, keys);
201
202         final var leaderPath = YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath)
203             .node(lead);
204
205         final var leader = ImmutableNodes.leafNode(lead, "Updated leader");
206
207         final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
208         writeModification.write(leaderPath, leader);
209         writeModification.ready();
210
211         final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
212
213         LOG.debug("*************************");
214         LOG.debug("Before write into map entry (update of leader name): ");
215         LOG.debug("*************************");
216         LOG.debug(inMemoryDataTree.toString());
217
218         final var ex = assertThrows(LeafRefDataValidationFailedException.class,
219             () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
220         assertEquals(1, ex.getValidationsErrorsCount());
221
222         inMemoryDataTree.commit(writeContributorsCandidate);
223
224         LOG.debug("*************************");
225         LOG.debug("After write into map entry (update of leader name): ");
226         LOG.debug("*************************");
227         LOG.debug(inMemoryDataTree.toString());
228     }
229
230     private static void writeMapEntry() throws DataValidationFailedException {
231         final var mapEntryPath = NodeIdentifierWithPredicates.of(project, name, "New Project");
232
233         final var newProjectMapEntry = createProjectListEntry(
234                 "New Project", "New Project description ...",
235                 "Leader of New Project", "Owner of New Project");
236
237         final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
238         writeModification.write(YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath), newProjectMapEntry);
239         writeModification.ready();
240
241         final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
242
243         LOG.debug("*************************");
244         LOG.debug("Before map entry write: ");
245         LOG.debug("*************************");
246         LOG.debug(inMemoryDataTree.toString());
247
248         final var ex = assertThrows(LeafRefDataValidationFailedException.class,
249             () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
250         assertEquals(2, ex.getValidationsErrorsCount());
251
252         inMemoryDataTree.commit(writeContributorsCandidate);
253
254         LOG.debug("*************************");
255         LOG.debug("After map entry write: ");
256         LOG.debug("*************************");
257         LOG.debug(inMemoryDataTree.toString());
258     }
259
260     private static void write() throws DataValidationFailedException {
261         final var contributorContainer = createContributorContainer(
262             (ContainerSchemaNode) valModule.getDataChildByName(odlContributor));
263
264         final var contributorPath = YangInstanceIdentifier.of(odlContributor);
265         final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
266         writeModification.write(contributorPath, contributorContainer);
267
268         writeModification.write(YangInstanceIdentifier.of(l1),
269             ImmutableNodes.leafNode(l1, "Leafref l1 under the root"));
270         writeModification.write(YangInstanceIdentifier.of(l2),
271             ImmutableNodes.leafNode(l2, "Leafref target l2 under the root"));
272
273         writeModification.ready();
274         final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
275
276         LOG.debug("*************************");
277         LOG.debug("Before write: ");
278         LOG.debug("*************************");
279         LOG.debug(inMemoryDataTree.toString());
280
281         final var ex = assertThrows(LeafRefDataValidationFailedException.class,
282             () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
283         assertEquals(12, ex.getValidationsErrorsCount());
284
285         inMemoryDataTree.commit(writeContributorsCandidate);
286
287         LOG.debug("*************************");
288         LOG.debug("After write: ");
289         LOG.debug("*************************");
290         LOG.debug(inMemoryDataTree.toString());
291     }
292
293     private static void write2() throws DataValidationFailedException {
294         final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
295         writeModification.write(YangInstanceIdentifier.of(odl).node(con1), ImmutableNodes.newContainerBuilder()
296             .withNodeIdentifier(new NodeIdentifier(con1))
297             .addChild(ImmutableNodes.leafNode(l1, "l1 value"))
298             .build());
299         writeModification.write(YangInstanceIdentifier.of(odl).node(ch1), createChoiceNode());
300         writeModification.write(YangInstanceIdentifier.of(odl).node(con3), createCon3Node());
301         writeModification.write(YangInstanceIdentifier.of(odl).node(leafrefLeafList), createLeafRefLeafListNode());
302         writeModification.ready();
303
304         final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
305
306         LOG.debug("*************************");
307         LOG.debug("Before write2: ");
308         LOG.debug("*************************");
309         LOG.debug(inMemoryDataTree.toString());
310
311         final var ex = assertThrows(LeafRefDataValidationFailedException.class,
312             () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
313         assertEquals(6, ex.getValidationsErrorsCount());
314
315         inMemoryDataTree.commit(writeContributorsCandidate);
316
317         LOG.debug("*************************");
318         LOG.debug("After write2: ");
319         LOG.debug("*************************");
320         LOG.debug(inMemoryDataTree.toString());
321     }
322
323     private static @NonNull LeafSetNode<Object> createLeafRefLeafListNode() {
324         return ImmutableNodes.newSystemLeafSetBuilder()
325             .withNodeIdentifier(new NodeIdentifier(leafrefLeafList))
326             .addChild(ImmutableNodes.leafSetEntry(leafrefLeafList, "k1"))
327             .addChild(ImmutableNodes.leafSetEntry(leafrefLeafList, "k2"))
328             .addChild(ImmutableNodes.leafSetEntry(leafrefLeafList, "k3"))
329             .build();
330     }
331
332     private static ContainerNode createCon3Node() {
333         return ImmutableNodes.newContainerBuilder()
334             .withNodeIdentifier(new NodeIdentifier(con3))
335             .addChild(ImmutableNodes.newChoiceBuilder()
336                 .withNodeIdentifier(new NodeIdentifier(choiceInCon3))
337                 .addChild(ImmutableNodes.newSystemMapBuilder()
338                     .withNodeIdentifier(new NodeIdentifier(list3InChoice))
339                     .addChild(createList3Entry("k1", "val1", "valA", "valX"))
340                     .addChild(createList3Entry("k2", "val2", "valB", "valY"))
341                     .build())
342                 .build())
343             .build();
344     }
345
346     private static MapEntryNode createList3Entry(final String keyVal,final String l3Val1, final String l3Val2,
347             final String l3Val3) {
348         return ImmutableNodes.newMapEntryBuilder()
349             .withNodeIdentifier(NodeIdentifierWithPredicates.of(list3InChoice, k, keyVal))
350             .addChild(ImmutableNodes.leafNode(k, keyVal))
351             .addChild(ImmutableNodes.newSystemLeafSetBuilder()
352                 .withNodeIdentifier(new NodeIdentifier(l3))
353                 .addChild(ImmutableNodes.leafSetEntry(l3, l3Val1))
354                 .addChild(ImmutableNodes.leafSetEntry(l3, l3Val2))
355                 .addChild(ImmutableNodes.leafSetEntry(l3, l3Val3))
356                 .build())
357             .build();
358     }
359
360     private static ChoiceNode createChoiceNode() {
361         return ImmutableNodes.newChoiceBuilder()
362             .withNodeIdentifier(new NodeIdentifier(ch1))
363             .addChild(ImmutableNodes.newChoiceBuilder()
364                 .withNodeIdentifier(new NodeIdentifier(ch2))
365                 .addChild(ImmutableNodes.newSystemMapBuilder()
366                     .withNodeIdentifier(new NodeIdentifier(listInChoice))
367                     .addChild(createListInChoiceEntry("key1", "leafref-in-choice value", "val1"))
368                     .addChild(createListInChoiceEntry("key2", "l1 value", "val2"))
369                     .addChild(createListInChoiceEntry("key3", "l1 value", "val3"))
370                     .build())
371                 .build())
372             .build();
373     }
374
375     private static MapEntryNode createListInChoiceEntry(final String keyVal, final String leafrefInChoiceVal,
376             final String leafrefInChoiceToChoiceVal) {
377         return ImmutableNodes.newMapEntryBuilder()
378             .withNodeIdentifier(NodeIdentifierWithPredicates.of(listInChoice, listInChoiceKey, keyVal))
379             .addChild(ImmutableNodes.leafNode(listInChoiceKey, keyVal))
380             .addChild(ImmutableNodes.leafNode(leafrefInChoice, leafrefInChoiceVal))
381             .addChild(ImmutableNodes.leafNode(leafrefInChoiceToChoice, leafrefInChoiceToChoiceVal))
382             .build();
383     }
384
385     private static void delete() throws DataValidationFailedException {
386         final var delete = inMemoryDataTree.takeSnapshot().newModification();
387         delete.delete(YangInstanceIdentifier.of(odlContributor));
388         delete.ready();
389
390         final var deleteContributorsCanditate = inMemoryDataTree.prepare(delete);
391
392         LOG.debug("*************************");
393         LOG.debug("Before delete: ");
394         LOG.debug("*************************");
395         LOG.debug(inMemoryDataTree.toString());
396
397
398         final var ex = assertThrows(LeafRefDataValidationFailedException.class,
399             () -> LeafRefValidation.validate(deleteContributorsCanditate, rootLeafRefContext));
400         assertEquals(6, ex.getValidationsErrorsCount());
401
402         inMemoryDataTree.commit(deleteContributorsCanditate);
403
404         LOG.debug("*************************");
405         LOG.debug("After delete: ");
406         LOG.debug("*************************");
407         LOG.debug(inMemoryDataTree.toString());
408     }
409
410     private static ContainerNode createContributorContainer(final ContainerSchemaNode contributorCont) {
411         return ImmutableNodes.newContainerBuilder()
412             .withNodeIdentifier(new NodeIdentifier(odlContributor))
413             .addChild(createContributorList((ListSchemaNode) contributorCont.getDataChildByName(contributor)))
414             .build();
415
416     }
417
418     private static SystemMapNode createContributorList(final ListSchemaNode contributorListSchemaNode) {
419         return ImmutableNodes.newSystemMapBuilder()
420             .withNodeIdentifier(new NodeIdentifier(contributor))
421             .addChild(createContributorListEntry("Leader of Yangtools", "Yangtools Leader name", "Yangtools",
422                 "Yangtools description ..."))
423             .addChild(createContributorListEntry("Leader of MD-SAL", "MD-SAL Leader name", "MD-SAL",
424                 "MD-SAL description ..."))
425             .addChild(createContributorListEntry("Leader of Controller", "Controller Leader name", "Controller",
426                 "Controller description ..."))
427             .addChild(createContributorListEntry("jdoe", "John Doe", "MD-SAL", "Yangtools description ..."))
428             .addChild(createContributorListEntry("foo", "foo name", "Controller", "MD-SAL description ..."))
429             .addChild(createContributorListEntry("bar", "bar name", "Yangtools", "Controller description ..."))
430             .addChild(createContributorListEntry("baz", "baz name", "Unknown Project",
431                 "Unknown Project description ..."))
432             .addChild(createContributorListEntry("pk", "pk name", "Unknown Project 2", "Controller description ..."))
433             .build();
434     }
435
436     private static MapEntryNode createContributorListEntry(final String loginVal, final String contributorNameVal,
437             final String odlProjectNameVal, final String odlProjectDescVal) {
438         return ImmutableNodes.newMapEntryBuilder()
439             .withNodeIdentifier(NodeIdentifierWithPredicates.of(contributor, login, loginVal))
440             .addChild(ImmutableNodes.leafNode(login, loginVal))
441             .addChild(ImmutableNodes.leafNode(contributorName, contributorNameVal))
442             .addChild(ImmutableNodes.leafNode(odlProjectName, odlProjectNameVal))
443             .addChild(ImmutableNodes.leafNode(odlProjectDesc, odlProjectDescVal))
444             .build();
445     }
446
447     private static ContainerNode createOdlContainer() {
448         return ImmutableNodes.newContainerBuilder()
449             .withNodeIdentifier(new NodeIdentifier(odl))
450             .addChild(createProjectList())
451             .build();
452     }
453
454     private static SystemMapNode createProjectList() {
455         return ImmutableNodes.newSystemMapBuilder()
456             .withNodeIdentifier(new NodeIdentifier(project))
457             .addChild(createProjectListEntry("Yangtools", "Yangtools description ...", "Leader of Yangtools",
458                 "Owner of Yangtools"))
459             .addChild(createProjectListEntry("MD-SAL", "MD-SAL description ...", "Leader of MD-SAL", "Owner of MD-SAL"))
460             .addChild(createProjectListEntry("Controller", "Controller description ...", "Leader of Controller",
461             "Owner of Controller")).build();
462     }
463
464     private static MapEntryNode createProjectListEntry(final String nameVal, final String descVal, final String leadVal,
465             final String ownerVal) {
466         return ImmutableNodes.newMapEntryBuilder()
467             .withNodeIdentifier(NodeIdentifierWithPredicates.of(project, name, nameVal))
468             .addChild(ImmutableNodes.leafNode(name, nameVal))
469             .addChild(ImmutableNodes.leafNode(desc, descVal))
470             .addChild(ImmutableNodes.leafNode(lead, leadVal))
471             .addChild(ImmutableNodes.leafNode(owner, ownerVal))
472             .build();
473     }
474
475     private static ContainerNode createBasicContributorContainer() {
476         return ImmutableNodes.newContainerBuilder()
477             .withNodeIdentifier(new NodeIdentifier(odlContributor))
478             .addChild(createBasicContributorList())
479             .build();
480     }
481
482     private static SystemMapNode createBasicContributorList() {
483         return ImmutableNodes.newSystemMapBuilder()
484             .withNodeIdentifier(new NodeIdentifier(contributor))
485             .addChild(createContributorListEntry("Leader of Yangtools", "Yangtools Leader name", "Yangtools",
486                 "Yangtools description ..."))
487             .addChild(createContributorListEntry("Leader of MD-SAL", "MD-SAL Leader name", "MD-SAL",
488                 "MD-SAL description ..."))
489             .addChild(createContributorListEntry("Leader of Controller", "Controller Leader name", "Controller",
490                 "Controller description ...")).build();
491     }
492 }