2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.data.impl.leafref.context;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertThrows;
13 import java.util.HashMap;
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;
51 public class DataTreeCandidateValidatorTest {
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;
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;
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;
85 private static QName listInChoiceKey;
86 private static QName k;
88 private static QName leafrefLeafList;
90 private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateValidatorTest.class);
91 private static final String NEW_LINE = System.getProperty("line.separator");
94 public static void init() throws DataValidationFailedException {
95 context = YangParserTestUtils.parseYangResourceDirectory("/leafref-validation");
97 for (final Module module : context.getModules()) {
98 if (module.getName().equals("leafref-validation")) {
103 valModuleQname = valModule.getQNameModule();
104 rootLeafRefContext = LeafRefContext.create(context);
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");
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");
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");
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");
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");
136 listInChoiceKey = QName.create(valModuleQname, "list-in-choice-key");
137 k = QName.create(valModuleQname, "k");
139 leafrefLeafList = QName.create(valModuleQname, "leafref-leaf-list");
141 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL, context);
143 final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
145 final ContainerNode odlProjectContainer = createOdlContainer();
147 final YangInstanceIdentifier path = YangInstanceIdentifier.of(odl);
148 initialDataTreeModification.write(path, odlProjectContainer);
149 initialDataTreeModification.ready();
151 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree
152 .prepare(initialDataTreeModification);
153 inMemoryDataTree.commit(writeContributorsCandidate);
157 public static void cleanup() {
158 inMemoryDataTree = null;
159 rootLeafRefContext = null;
165 public void dataTreeCanditateValidationTest() throws DataValidationFailedException {
179 private static void writeContributors() throws DataValidationFailedException {
181 final ContainerNode contributorContainer = createBasicContributorContainer();
183 final YangInstanceIdentifier contributorPath = YangInstanceIdentifier.of(odlContributor);
184 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
185 writeModification.write(contributorPath, contributorContainer);
186 writeModification.ready();
188 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree
189 .prepare(writeModification);
191 LOG.debug("*************************");
192 LOG.debug("Before write of contributors: ");
193 LOG.debug("*************************");
194 LOG.debug(inMemoryDataTree.toString());
196 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
197 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
198 assertEquals(3, ex.getValidationsErrorsCount());
200 inMemoryDataTree.commit(writeContributorsCandidate);
202 LOG.debug("*************************");
203 LOG.debug("After write of contributors: ");
204 LOG.debug("*************************");
205 LOG.debug(inMemoryDataTree.toString());
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);
213 final YangInstanceIdentifier leaderPath = YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath)
216 final LeafNode<String> leader = ImmutableNodes.leafNode(lead, "Updated leader");
218 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
219 writeModification.write(leaderPath, leader);
220 writeModification.ready();
222 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
224 LOG.debug("*************************");
225 LOG.debug("Before write into map entry (update of leader name): ");
226 LOG.debug("*************************");
227 LOG.debug(inMemoryDataTree.toString());
229 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
230 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
231 assertEquals(1, ex.getValidationsErrorsCount());
233 inMemoryDataTree.commit(writeContributorsCandidate);
235 LOG.debug("*************************");
236 LOG.debug("After write into map entry (update of leader name): ");
237 LOG.debug("*************************");
238 LOG.debug(inMemoryDataTree.toString());
241 private static void writeMapEntry() throws DataValidationFailedException {
242 final NodeIdentifierWithPredicates mapEntryPath = NodeIdentifierWithPredicates.of(project, name, "New Project");
244 final MapEntryNode newProjectMapEntry = createProjectListEntry(
245 "New Project", "New Project description ...",
246 "Leader of New Project", "Owner of New Project");
248 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
249 writeModification.write(YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath), newProjectMapEntry);
250 writeModification.ready();
252 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
254 LOG.debug("*************************");
255 LOG.debug("Before map entry write: ");
256 LOG.debug("*************************");
257 LOG.debug(inMemoryDataTree.toString());
259 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
260 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
261 assertEquals(2, ex.getValidationsErrorsCount());
263 inMemoryDataTree.commit(writeContributorsCandidate);
265 LOG.debug("*************************");
266 LOG.debug("After map entry write: ");
267 LOG.debug("*************************");
268 LOG.debug(inMemoryDataTree.toString());
271 private static void write() throws DataValidationFailedException {
272 final ContainerNode contributorContainer = createContributorContainer(
273 (ContainerSchemaNode) valModule.getDataChildByName(odlContributor));
275 final YangInstanceIdentifier contributorPath = YangInstanceIdentifier.of(odlContributor);
276 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
277 writeModification.write(contributorPath, contributorContainer);
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"));
284 writeModification.ready();
285 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
287 LOG.debug("*************************");
288 LOG.debug("Before write: ");
289 LOG.debug("*************************");
290 LOG.debug(inMemoryDataTree.toString());
292 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
293 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
294 assertEquals(12, ex.getValidationsErrorsCount());
296 inMemoryDataTree.commit(writeContributorsCandidate);
298 LOG.debug("*************************");
299 LOG.debug("After write: ");
300 LOG.debug("*************************");
301 LOG.debug(inMemoryDataTree.toString());
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"))
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();
315 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
317 LOG.debug("*************************");
318 LOG.debug("Before write2: ");
319 LOG.debug("*************************");
320 LOG.debug(inMemoryDataTree.toString());
322 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
323 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
324 assertEquals(6, ex.getValidationsErrorsCount());
326 inMemoryDataTree.commit(writeContributorsCandidate);
328 LOG.debug("*************************");
329 LOG.debug("After write2: ");
330 LOG.debug("*************************");
331 LOG.debug(inMemoryDataTree.toString());
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"))
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"))
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))
371 private static LeafSetEntryNode<Object> createLeafSetEntry(final QName qname, final String val) {
372 return Builders.leafSetEntryBuilder()
373 .withNodeIdentifier(new NodeWithValue<>(qname, val))
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"))
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))
403 private static void delete() throws DataValidationFailedException {
404 final DataTreeModification delete = inMemoryDataTree.takeSnapshot().newModification();
405 delete.delete(YangInstanceIdentifier.of(odlContributor));
408 final DataTreeCandidate deleteContributorsCanditate = inMemoryDataTree.prepare(delete);
410 LOG.debug("*************************");
411 LOG.debug("Before delete: ");
412 LOG.debug("*************************");
413 LOG.debug(inMemoryDataTree.toString());
416 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
417 () -> LeafRefValidation.validate(deleteContributorsCanditate, rootLeafRefContext));
418 assertEquals(6, ex.getValidationsErrorsCount());
420 inMemoryDataTree.commit(deleteContributorsCanditate);
422 LOG.debug("*************************");
423 LOG.debug("After delete: ");
424 LOG.debug("*************************");
425 LOG.debug(inMemoryDataTree.toString());
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()))
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 ..."))
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))
465 private static ContainerNode createOdlContainer() {
466 return Builders.containerBuilder()
467 .withNodeIdentifier(new NodeIdentifier(odl))
468 .addChild(createProjectList())
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();
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))
493 private static ContainerNode createBasicContributorContainer() {
494 return Builders.containerBuilder()
495 .withNodeIdentifier(new NodeIdentifier(odlContributor))
496 .addChild(createBasicContributorList())
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();