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.tree.leafref;
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.impl.schema.Builders;
33 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
34 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
35 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
36 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
37 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
38 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
39 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
40 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
41 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
42 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
43 import org.opendaylight.yangtools.yang.model.api.Module;
44 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
48 public class DataTreeCandidateValidatorTest {
50 private static EffectiveModelContext context;
51 private static Module valModule;
52 private static QNameModule valModuleQname;
53 private static LeafRefContext rootLeafRefContext;
54 public static DataTree inMemoryDataTree;
56 private static QName odl;
57 private static QName project;
58 private static QName name;
59 private static QName desc;
60 private static QName lead;
61 private static QName owner;
62 private static QName odlContributor;
63 private static QName contributor;
64 private static QName odlProjectName;
65 private static QName odlProjectDesc;
66 private static QName login;
67 private static QName contributorName;
68 private static QName l1;
69 private static QName l2;
70 private static QName con1;
71 private static QName ch1;
72 private static QName ch2;
73 private static QName leafrefInChoice;
74 private static QName listInChoice;
76 private static QName leafrefInChoiceToChoice;
77 private static QName con3;
78 private static QName list3InChoice;
79 private static QName l3;
80 private static QName choiceInCon3;
82 private static QName listInChoiceKey;
83 private static QName k;
85 private static QName leafrefLeafList;
87 private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateValidatorTest.class);
88 private static final String NEW_LINE = System.getProperty("line.separator");
91 public static void init() throws DataValidationFailedException {
92 context = YangParserTestUtils.parseYangResourceDirectory("/leafref-validation");
94 for (final Module module : context.getModules()) {
95 if (module.getName().equals("leafref-validation")) {
100 valModuleQname = valModule.getQNameModule();
101 rootLeafRefContext = LeafRefContext.create(context);
103 odl = QName.create(valModuleQname, "odl-project");
104 project = QName.create(valModuleQname, "project");
105 name = QName.create(valModuleQname, "name");
106 desc = QName.create(valModuleQname, "desc");
107 lead = QName.create(valModuleQname, "project-lead");
108 owner = QName.create(valModuleQname, "project-owner");
110 odlContributor = QName.create(valModuleQname, "odl-contributor");
111 contributor = QName.create(valModuleQname, "contributor");
112 odlProjectName = QName.create(valModuleQname, "odl-project-name");
113 login = QName.create(valModuleQname, "login");
114 contributorName = QName.create(valModuleQname, "contributor-name");
116 con1 = QName.create(valModuleQname, "con1");
117 l1 = QName.create(valModuleQname, "l1");
118 l2 = QName.create(valModuleQname, "l2");
119 odlProjectDesc = QName.create(valModuleQname, "odl-project-desc");
121 ch1 = QName.create(valModuleQname, "ch1");
122 ch2 = QName.create(valModuleQname, "ch2");
123 leafrefInChoice = QName.create(valModuleQname, "leafref-in-choice");
124 listInChoice = QName.create(valModuleQname, "list-in-choice");
126 leafrefInChoiceToChoice = QName.create(valModuleQname, "leafref-in-choice-to-choice");
127 con3 = QName.create(valModuleQname, "con3");
128 list3InChoice = QName.create(valModuleQname, "list3-in-choice");
129 l3 = QName.create(valModuleQname, "l3");
130 choiceInCon3 = QName.create(valModuleQname, "choice-in-con3");
132 listInChoiceKey = QName.create(valModuleQname, "list-in-choice-key");
133 k = QName.create(valModuleQname, "k");
135 leafrefLeafList = QName.create(valModuleQname, "leafref-leaf-list");
137 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL, context);
139 final DataTreeModification initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
141 final ContainerNode odlProjectContainer = createOdlContainer();
143 final YangInstanceIdentifier path = YangInstanceIdentifier.of(odl);
144 initialDataTreeModification.write(path, odlProjectContainer);
145 initialDataTreeModification.ready();
147 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree
148 .prepare(initialDataTreeModification);
149 inMemoryDataTree.commit(writeContributorsCandidate);
153 public static void cleanup() {
154 inMemoryDataTree = null;
155 rootLeafRefContext = null;
161 public void dataTreeCanditateValidationTest() throws DataValidationFailedException {
175 private static void writeContributors() throws DataValidationFailedException {
177 final ContainerNode contributorContainer = createBasicContributorContainer();
179 final YangInstanceIdentifier contributorPath = YangInstanceIdentifier.of(odlContributor);
180 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
181 writeModification.write(contributorPath, contributorContainer);
182 writeModification.ready();
184 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree
185 .prepare(writeModification);
187 LOG.debug("*************************");
188 LOG.debug("Before write of contributors: ");
189 LOG.debug("*************************");
190 LOG.debug(inMemoryDataTree.toString());
192 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
193 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
194 assertEquals(3, ex.getValidationsErrorsCount());
196 inMemoryDataTree.commit(writeContributorsCandidate);
198 LOG.debug("*************************");
199 LOG.debug("After write of contributors: ");
200 LOG.debug("*************************");
201 LOG.debug(inMemoryDataTree.toString());
204 private static void writeIntoMapEntry() throws DataValidationFailedException {
205 final Map<QName, Object> keys = new HashMap<>();
206 keys.put(name, "New Project");
207 final NodeIdentifierWithPredicates mapEntryPath = NodeIdentifierWithPredicates.of(project, keys);
209 final YangInstanceIdentifier leaderPath = YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath)
212 final LeafNode<String> leader = ImmutableNodes.leafNode(lead, "Updated leader");
214 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
215 writeModification.write(leaderPath, leader);
216 writeModification.ready();
218 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
220 LOG.debug("*************************");
221 LOG.debug("Before write into map entry (update of leader name): ");
222 LOG.debug("*************************");
223 LOG.debug(inMemoryDataTree.toString());
225 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
226 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
227 assertEquals(1, ex.getValidationsErrorsCount());
229 inMemoryDataTree.commit(writeContributorsCandidate);
231 LOG.debug("*************************");
232 LOG.debug("After write into map entry (update of leader name): ");
233 LOG.debug("*************************");
234 LOG.debug(inMemoryDataTree.toString());
237 private static void writeMapEntry() throws DataValidationFailedException {
238 final NodeIdentifierWithPredicates mapEntryPath = NodeIdentifierWithPredicates.of(project, name, "New Project");
240 final MapEntryNode newProjectMapEntry = createProjectListEntry(
241 "New Project", "New Project description ...",
242 "Leader of New Project", "Owner of New Project");
244 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
245 writeModification.write(YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath), newProjectMapEntry);
246 writeModification.ready();
248 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
250 LOG.debug("*************************");
251 LOG.debug("Before map entry write: ");
252 LOG.debug("*************************");
253 LOG.debug(inMemoryDataTree.toString());
255 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
256 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
257 assertEquals(2, ex.getValidationsErrorsCount());
259 inMemoryDataTree.commit(writeContributorsCandidate);
261 LOG.debug("*************************");
262 LOG.debug("After map entry write: ");
263 LOG.debug("*************************");
264 LOG.debug(inMemoryDataTree.toString());
267 private static void write() throws DataValidationFailedException {
268 final ContainerNode contributorContainer = createContributorContainer(
269 (ContainerSchemaNode) valModule.getDataChildByName(odlContributor));
271 final YangInstanceIdentifier contributorPath = YangInstanceIdentifier.of(odlContributor);
272 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
273 writeModification.write(contributorPath, contributorContainer);
275 writeModification.write(YangInstanceIdentifier.of(l1),
276 ImmutableNodes.leafNode(l1, "Leafref l1 under the root"));
277 writeModification.write(YangInstanceIdentifier.of(l2),
278 ImmutableNodes.leafNode(l2, "Leafref target l2 under the root"));
280 writeModification.ready();
281 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
283 LOG.debug("*************************");
284 LOG.debug("Before write: ");
285 LOG.debug("*************************");
286 LOG.debug(inMemoryDataTree.toString());
288 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
289 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
290 assertEquals(12, ex.getValidationsErrorsCount());
292 inMemoryDataTree.commit(writeContributorsCandidate);
294 LOG.debug("*************************");
295 LOG.debug("After write: ");
296 LOG.debug("*************************");
297 LOG.debug(inMemoryDataTree.toString());
300 private static void write2() throws DataValidationFailedException {
301 final DataTreeModification writeModification = inMemoryDataTree.takeSnapshot().newModification();
302 writeModification.write(YangInstanceIdentifier.of(odl).node(con1), Builders.containerBuilder()
303 .withNodeIdentifier(new NodeIdentifier(con1))
304 .addChild(ImmutableNodes.leafNode(l1, "l1 value"))
306 writeModification.write(YangInstanceIdentifier.of(odl).node(ch1), createChoiceNode());
307 writeModification.write(YangInstanceIdentifier.of(odl).node(con3), createCon3Node());
308 writeModification.write(YangInstanceIdentifier.of(odl).node(leafrefLeafList), createLeafRefLeafListNode());
309 writeModification.ready();
311 final DataTreeCandidate writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
313 LOG.debug("*************************");
314 LOG.debug("Before write2: ");
315 LOG.debug("*************************");
316 LOG.debug(inMemoryDataTree.toString());
318 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
319 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
320 assertEquals(6, ex.getValidationsErrorsCount());
322 inMemoryDataTree.commit(writeContributorsCandidate);
324 LOG.debug("*************************");
325 LOG.debug("After write2: ");
326 LOG.debug("*************************");
327 LOG.debug(inMemoryDataTree.toString());
330 private static @NonNull LeafSetNode<Object> createLeafRefLeafListNode() {
331 return Builders.leafSetBuilder()
332 .withNodeIdentifier(new NodeIdentifier(leafrefLeafList))
333 .addChild(createLeafSetEntry(leafrefLeafList, "k1"))
334 .addChild(createLeafSetEntry(leafrefLeafList, "k2"))
335 .addChild(createLeafSetEntry(leafrefLeafList, "k3"))
339 private static ContainerNode createCon3Node() {
340 return Builders.containerBuilder()
341 .withNodeIdentifier(new NodeIdentifier(con3))
342 .addChild(Builders.choiceBuilder()
343 .withNodeIdentifier(new NodeIdentifier(choiceInCon3))
344 .addChild(Builders.mapBuilder()
345 .withNodeIdentifier(new NodeIdentifier(list3InChoice))
346 .addChild(createList3Entry("k1", "val1", "valA", "valX"))
347 .addChild(createList3Entry("k2", "val2", "valB", "valY"))
353 private static MapEntryNode createList3Entry(final String keyVal,final String l3Val1, final String l3Val2,
354 final String l3Val3) {
355 return Builders.mapEntryBuilder()
356 .withNodeIdentifier(NodeIdentifierWithPredicates.of(list3InChoice, k, keyVal))
357 .addChild(ImmutableNodes.leafNode(k, keyVal))
358 .addChild(Builders.leafSetBuilder()
359 .withNodeIdentifier(new NodeIdentifier(l3))
360 .addChild(createLeafSetEntry(l3, l3Val1))
361 .addChild(createLeafSetEntry(l3, l3Val2))
362 .addChild(createLeafSetEntry(l3, l3Val3))
367 private static LeafSetEntryNode<Object> createLeafSetEntry(final QName qname, final String val) {
368 return Builders.leafSetEntryBuilder()
369 .withNodeIdentifier(new NodeWithValue<>(qname, val))
374 private static ChoiceNode createChoiceNode() {
375 return Builders.choiceBuilder()
376 .withNodeIdentifier(new NodeIdentifier(ch1))
377 .addChild(Builders.choiceBuilder()
378 .withNodeIdentifier(new NodeIdentifier(ch2))
379 .addChild(Builders.mapBuilder()
380 .withNodeIdentifier(new NodeIdentifier(listInChoice))
381 .addChild(createListInChoiceEntry("key1", "leafref-in-choice value", "val1"))
382 .addChild(createListInChoiceEntry("key2", "l1 value", "val2"))
383 .addChild(createListInChoiceEntry("key3", "l1 value", "val3"))
389 private static MapEntryNode createListInChoiceEntry(final String keyVal, final String leafrefInChoiceVal,
390 final String leafrefInChoiceToChoiceVal) {
391 return Builders.mapEntryBuilder()
392 .withNodeIdentifier(NodeIdentifierWithPredicates.of(listInChoice, listInChoiceKey, keyVal))
393 .addChild(ImmutableNodes.leafNode(listInChoiceKey, keyVal))
394 .addChild(ImmutableNodes.leafNode(leafrefInChoice, leafrefInChoiceVal))
395 .addChild(ImmutableNodes.leafNode(leafrefInChoiceToChoice, leafrefInChoiceToChoiceVal))
399 private static void delete() throws DataValidationFailedException {
400 final DataTreeModification delete = inMemoryDataTree.takeSnapshot().newModification();
401 delete.delete(YangInstanceIdentifier.of(odlContributor));
404 final DataTreeCandidate deleteContributorsCanditate = inMemoryDataTree.prepare(delete);
406 LOG.debug("*************************");
407 LOG.debug("Before delete: ");
408 LOG.debug("*************************");
409 LOG.debug(inMemoryDataTree.toString());
412 final LeafRefDataValidationFailedException ex = assertThrows(LeafRefDataValidationFailedException.class,
413 () -> LeafRefValidation.validate(deleteContributorsCanditate, rootLeafRefContext));
414 assertEquals(6, ex.getValidationsErrorsCount());
416 inMemoryDataTree.commit(deleteContributorsCanditate);
418 LOG.debug("*************************");
419 LOG.debug("After delete: ");
420 LOG.debug("*************************");
421 LOG.debug(inMemoryDataTree.toString());
424 private static ContainerNode createContributorContainer(final ContainerSchemaNode contributorCont) {
425 return Builders.containerBuilder()
426 .withNodeIdentifier(new NodeIdentifier(odlContributor))
427 .addChild(createContributorList((ListSchemaNode) contributorCont.findDataChildByName(contributor).get()))
432 private static SystemMapNode createContributorList(final ListSchemaNode contributorListSchemaNode) {
433 return Builders.mapBuilder()
434 .withNodeIdentifier(new NodeIdentifier(contributor))
435 .addChild(createContributorListEntry("Leader of Yangtools", "Yangtools Leader name", "Yangtools",
436 "Yangtools description ..."))
437 .addChild(createContributorListEntry("Leader of MD-SAL", "MD-SAL Leader name", "MD-SAL",
438 "MD-SAL description ..."))
439 .addChild(createContributorListEntry("Leader of Controller", "Controller Leader name", "Controller",
440 "Controller description ..."))
441 .addChild(createContributorListEntry("jdoe", "John Doe", "MD-SAL", "Yangtools description ..."))
442 .addChild(createContributorListEntry("foo", "foo name", "Controller", "MD-SAL description ..."))
443 .addChild(createContributorListEntry("bar", "bar name", "Yangtools", "Controller description ..."))
444 .addChild(createContributorListEntry("baz", "baz name", "Unknown Project",
445 "Unknown Project description ..."))
446 .addChild(createContributorListEntry("pk", "pk name", "Unknown Project 2", "Controller description ..."))
450 private static MapEntryNode createContributorListEntry(final String loginVal, final String contributorNameVal,
451 final String odlProjectNameVal, final String odlProjectDescVal) {
452 return Builders.mapEntryBuilder()
453 .withNodeIdentifier(NodeIdentifierWithPredicates.of(contributor, login, loginVal))
454 .addChild(ImmutableNodes.leafNode(login, loginVal))
455 .addChild(ImmutableNodes.leafNode(contributorName, contributorNameVal))
456 .addChild(ImmutableNodes.leafNode(odlProjectName, odlProjectNameVal))
457 .addChild(ImmutableNodes.leafNode(odlProjectDesc, odlProjectDescVal))
461 private static ContainerNode createOdlContainer() {
462 return Builders.containerBuilder()
463 .withNodeIdentifier(new NodeIdentifier(odl))
464 .addChild(createProjectList())
468 private static SystemMapNode createProjectList() {
469 return Builders.mapBuilder()
470 .withNodeIdentifier(new NodeIdentifier(project))
471 .addChild(createProjectListEntry("Yangtools", "Yangtools description ...", "Leader of Yangtools",
472 "Owner of Yangtools"))
473 .addChild(createProjectListEntry("MD-SAL", "MD-SAL description ...", "Leader of MD-SAL", "Owner of MD-SAL"))
474 .addChild(createProjectListEntry("Controller", "Controller description ...", "Leader of Controller",
475 "Owner of Controller")).build();
478 private static MapEntryNode createProjectListEntry(final String nameVal, final String descVal, final String leadVal,
479 final String ownerVal) {
480 return Builders.mapEntryBuilder()
481 .withNodeIdentifier(NodeIdentifierWithPredicates.of(project, name, nameVal))
482 .addChild(ImmutableNodes.leafNode(name, nameVal))
483 .addChild(ImmutableNodes.leafNode(desc, descVal))
484 .addChild(ImmutableNodes.leafNode(lead, leadVal))
485 .addChild(ImmutableNodes.leafNode(owner, ownerVal))
489 private static ContainerNode createBasicContributorContainer() {
490 return Builders.containerBuilder()
491 .withNodeIdentifier(new NodeIdentifier(odlContributor))
492 .addChild(createBasicContributorList())
496 private static SystemMapNode createBasicContributorList() {
497 return Builders.mapBuilder()
498 .withNodeIdentifier(new NodeIdentifier(contributor))
499 .addChild(createContributorListEntry("Leader of Yangtools", "Yangtools Leader name", "Yangtools",
500 "Yangtools description ..."))
501 .addChild(createContributorListEntry("Leader of MD-SAL", "MD-SAL Leader name", "MD-SAL",
502 "MD-SAL description ..."))
503 .addChild(createContributorListEntry("Leader of Controller", "Controller Leader name", "Controller",
504 "Controller description ...")).build();