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.jupiter.api.Assertions.assertEquals;
11 import static org.junit.jupiter.api.Assertions.assertThrows;
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;
41 public class DataTreeCandidateValidatorTest {
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;
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;
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;
75 private static QName listInChoiceKey;
76 private static QName k;
78 private static QName leafrefLeafList;
80 private static final Logger LOG = LoggerFactory.getLogger(DataTreeCandidateValidatorTest.class);
81 private static final String NEW_LINE = System.getProperty("line.separator");
84 static void init() throws DataValidationFailedException {
85 context = YangParserTestUtils.parseYangResourceDirectory("/leafref-validation");
87 for (final var module : context.getModules()) {
88 if (module.getName().equals("leafref-validation")) {
93 valModuleQname = valModule.getQNameModule();
94 rootLeafRefContext = LeafRefContext.create(context);
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");
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");
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");
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");
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");
125 listInChoiceKey = QName.create(valModuleQname, "list-in-choice-key");
126 k = QName.create(valModuleQname, "k");
128 leafrefLeafList = QName.create(valModuleQname, "leafref-leaf-list");
130 inMemoryDataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_OPERATIONAL, context);
132 final var initialDataTreeModification = inMemoryDataTree.takeSnapshot().newModification();
134 final var odlProjectContainer = createOdlContainer();
136 final var path = YangInstanceIdentifier.of(odl);
137 initialDataTreeModification.write(path, odlProjectContainer);
138 initialDataTreeModification.ready();
140 final var writeContributorsCandidate = inMemoryDataTree
141 .prepare(initialDataTreeModification);
142 inMemoryDataTree.commit(writeContributorsCandidate);
146 static void cleanup() {
147 inMemoryDataTree = null;
148 rootLeafRefContext = null;
154 void dataTreeCanditateValidationTest() throws DataValidationFailedException {
168 private static void writeContributors() throws DataValidationFailedException {
170 final var contributorContainer = createBasicContributorContainer();
172 final var contributorPath = YangInstanceIdentifier.of(odlContributor);
173 final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
174 writeModification.write(contributorPath, contributorContainer);
175 writeModification.ready();
177 final var writeContributorsCandidate = inMemoryDataTree
178 .prepare(writeModification);
180 LOG.debug("*************************");
181 LOG.debug("Before write of contributors: ");
182 LOG.debug("*************************");
183 LOG.debug(inMemoryDataTree.toString());
185 final var ex = assertThrows(LeafRefDataValidationFailedException.class,
186 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
187 assertEquals(3, ex.getValidationsErrorsCount());
189 inMemoryDataTree.commit(writeContributorsCandidate);
191 LOG.debug("*************************");
192 LOG.debug("After write of contributors: ");
193 LOG.debug("*************************");
194 LOG.debug(inMemoryDataTree.toString());
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);
202 final var leaderPath = YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath)
205 final var leader = ImmutableNodes.leafNode(lead, "Updated leader");
207 final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
208 writeModification.write(leaderPath, leader);
209 writeModification.ready();
211 final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
213 LOG.debug("*************************");
214 LOG.debug("Before write into map entry (update of leader name): ");
215 LOG.debug("*************************");
216 LOG.debug(inMemoryDataTree.toString());
218 final var ex = assertThrows(LeafRefDataValidationFailedException.class,
219 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
220 assertEquals(1, ex.getValidationsErrorsCount());
222 inMemoryDataTree.commit(writeContributorsCandidate);
224 LOG.debug("*************************");
225 LOG.debug("After write into map entry (update of leader name): ");
226 LOG.debug("*************************");
227 LOG.debug(inMemoryDataTree.toString());
230 private static void writeMapEntry() throws DataValidationFailedException {
231 final var mapEntryPath = NodeIdentifierWithPredicates.of(project, name, "New Project");
233 final var newProjectMapEntry = createProjectListEntry(
234 "New Project", "New Project description ...",
235 "Leader of New Project", "Owner of New Project");
237 final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
238 writeModification.write(YangInstanceIdentifier.of(odl).node(project).node(mapEntryPath), newProjectMapEntry);
239 writeModification.ready();
241 final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
243 LOG.debug("*************************");
244 LOG.debug("Before map entry write: ");
245 LOG.debug("*************************");
246 LOG.debug(inMemoryDataTree.toString());
248 final var ex = assertThrows(LeafRefDataValidationFailedException.class,
249 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
250 assertEquals(2, ex.getValidationsErrorsCount());
252 inMemoryDataTree.commit(writeContributorsCandidate);
254 LOG.debug("*************************");
255 LOG.debug("After map entry write: ");
256 LOG.debug("*************************");
257 LOG.debug(inMemoryDataTree.toString());
260 private static void write() throws DataValidationFailedException {
261 final var contributorContainer = createContributorContainer(
262 (ContainerSchemaNode) valModule.getDataChildByName(odlContributor));
264 final var contributorPath = YangInstanceIdentifier.of(odlContributor);
265 final var writeModification = inMemoryDataTree.takeSnapshot().newModification();
266 writeModification.write(contributorPath, contributorContainer);
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"));
273 writeModification.ready();
274 final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
276 LOG.debug("*************************");
277 LOG.debug("Before write: ");
278 LOG.debug("*************************");
279 LOG.debug(inMemoryDataTree.toString());
281 final var ex = assertThrows(LeafRefDataValidationFailedException.class,
282 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
283 assertEquals(12, ex.getValidationsErrorsCount());
285 inMemoryDataTree.commit(writeContributorsCandidate);
287 LOG.debug("*************************");
288 LOG.debug("After write: ");
289 LOG.debug("*************************");
290 LOG.debug(inMemoryDataTree.toString());
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"))
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();
304 final var writeContributorsCandidate = inMemoryDataTree.prepare(writeModification);
306 LOG.debug("*************************");
307 LOG.debug("Before write2: ");
308 LOG.debug("*************************");
309 LOG.debug(inMemoryDataTree.toString());
311 final var ex = assertThrows(LeafRefDataValidationFailedException.class,
312 () -> LeafRefValidation.validate(writeContributorsCandidate, rootLeafRefContext));
313 assertEquals(6, ex.getValidationsErrorsCount());
315 inMemoryDataTree.commit(writeContributorsCandidate);
317 LOG.debug("*************************");
318 LOG.debug("After write2: ");
319 LOG.debug("*************************");
320 LOG.debug(inMemoryDataTree.toString());
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"))
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"))
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))
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"))
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))
385 private static void delete() throws DataValidationFailedException {
386 final var delete = inMemoryDataTree.takeSnapshot().newModification();
387 delete.delete(YangInstanceIdentifier.of(odlContributor));
390 final var deleteContributorsCanditate = inMemoryDataTree.prepare(delete);
392 LOG.debug("*************************");
393 LOG.debug("Before delete: ");
394 LOG.debug("*************************");
395 LOG.debug(inMemoryDataTree.toString());
398 final var ex = assertThrows(LeafRefDataValidationFailedException.class,
399 () -> LeafRefValidation.validate(deleteContributorsCanditate, rootLeafRefContext));
400 assertEquals(6, ex.getValidationsErrorsCount());
402 inMemoryDataTree.commit(deleteContributorsCanditate);
404 LOG.debug("*************************");
405 LOG.debug("After delete: ");
406 LOG.debug("*************************");
407 LOG.debug(inMemoryDataTree.toString());
410 private static ContainerNode createContributorContainer(final ContainerSchemaNode contributorCont) {
411 return ImmutableNodes.newContainerBuilder()
412 .withNodeIdentifier(new NodeIdentifier(odlContributor))
413 .addChild(createContributorList((ListSchemaNode) contributorCont.getDataChildByName(contributor)))
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 ..."))
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))
447 private static ContainerNode createOdlContainer() {
448 return ImmutableNodes.newContainerBuilder()
449 .withNodeIdentifier(new NodeIdentifier(odl))
450 .addChild(createProjectList())
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();
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))
475 private static ContainerNode createBasicContributorContainer() {
476 return ImmutableNodes.newContainerBuilder()
477 .withNodeIdentifier(new NodeIdentifier(odlContributor))
478 .addChild(createBasicContributorList())
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();