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