Fix mandatory enforcer failure on augmented nodes
[yangtools.git] / data / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / YT1276Test.java
diff --git a/data/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/YT1276Test.java b/data/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/YT1276Test.java
new file mode 100644 (file)
index 0000000..7e138cc
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.tree;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import java.util.Set;
+import java.util.function.Consumer;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
+import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class YT1276Test {
+    private static final QName FOO = QName.create("foo", "foo");
+    private static final QName BAR = QName.create(FOO, "bar");
+    private static final QName BAZ = QName.create(FOO, "baz");
+    private static final QName XYZZY_LEAF = QName.create(FOO, "xyzzy-leaf");
+    private static final QName XYZZY_AUGMENT = QName.create(FOO, "xyzzy-augment");
+
+    private static EffectiveModelContext MODEL;
+
+    private final DataTree tree = new InMemoryDataTreeFactory()
+        .create(DataTreeConfiguration.DEFAULT_CONFIGURATION, MODEL);
+
+    @BeforeClass
+    public static void beforeClass() {
+        MODEL = YangParserTestUtils.parseYangResource("/yt1276.yang");
+    }
+
+    @Test
+    public void testFooWithBar() throws DataValidationFailedException {
+        applyOperation(mod -> {
+            mod.write(YangInstanceIdentifier.of(FOO), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(FOO))
+                .withChild(Builders.augmentationBuilder()
+                    .withNodeIdentifier(new AugmentationIdentifier(Set.of(BAR)))
+                    .withChild(ImmutableNodes.leafNode(BAR, "xyzzy"))
+                    .build())
+                .build());
+        });
+    }
+
+    @Test
+    @Deprecated
+    public void testFooWithBarLegacy() throws DataValidationFailedException {
+        applyOperation(mod -> {
+            mod.write(YangInstanceIdentifier.of(FOO), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(FOO))
+                .withChild(ImmutableNodes.leafNode(BAR, "xyzzy"))
+                .build());
+        });
+    }
+
+    @Test
+    public void testFooWithoutBar() {
+        final IllegalArgumentException ex = assertFailsReady(mod -> {
+            mod.write(YangInstanceIdentifier.of(FOO), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(FOO))
+                .build());
+        });
+        assertEquals(
+            "Node (foo)foo is missing mandatory descendant /AugmentationIdentifier{childNames=[(foo)bar]}/(foo)bar",
+            ex.getMessage());
+    }
+
+    @Test
+    public void testBarWithXyzzy() throws DataValidationFailedException {
+        applyOperation(mod -> {
+            mod.write(YangInstanceIdentifier.of(BAR), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(BAR))
+                .withChild(Builders.choiceBuilder()
+                    .withNodeIdentifier(new NodeIdentifier(BAZ))
+                    .withChild(ImmutableNodes.leafNode(XYZZY_LEAF, "xyzzy"))
+                    .withChild(Builders.augmentationBuilder()
+                        .withNodeIdentifier(new AugmentationIdentifier(Set.of(XYZZY_AUGMENT)))
+                        .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT, "xyzzy"))
+                        .build())
+                    .build())
+                .build());
+        });
+    }
+
+    @Test
+    @Deprecated
+    public void testBarWithXyzzyLegacy() throws DataValidationFailedException {
+        applyOperation(mod -> {
+            mod.write(YangInstanceIdentifier.of(BAR), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(BAR))
+                .withChild(Builders.choiceBuilder()
+                    .withNodeIdentifier(new NodeIdentifier(BAZ))
+                    .withChild(ImmutableNodes.leafNode(XYZZY_LEAF, "xyzzy"))
+                    .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT, "xyzzy"))
+                    .build())
+                .build());
+        });
+    }
+
+    @Test
+    public void testBarWithoutXyzzyLeaf() {
+        final IllegalArgumentException ex = assertFailsReady(mod -> {
+            mod.write(YangInstanceIdentifier.of(BAR), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(BAR))
+                .withChild(Builders.choiceBuilder()
+                    .withNodeIdentifier(new NodeIdentifier(BAZ))
+                    .withChild(Builders.augmentationBuilder()
+                        .withNodeIdentifier(new AugmentationIdentifier(Set.of(XYZZY_AUGMENT)))
+                        .withChild(ImmutableNodes.leafNode(XYZZY_AUGMENT, "xyzzy"))
+                        .build())
+                    .build())
+                .build());
+        });
+        assertEquals(
+            "Node (foo)baz is missing mandatory descendant /(foo)xyzzy-leaf",
+            ex.getMessage());
+    }
+
+    @Test
+    public void testBarWithoutXyzzyAugment() {
+        final IllegalArgumentException ex = assertFailsReady(mod -> {
+            mod.write(YangInstanceIdentifier.of(BAR), Builders.containerBuilder()
+                .withNodeIdentifier(new NodeIdentifier(BAR))
+                .withChild(Builders.choiceBuilder()
+                    .withNodeIdentifier(new NodeIdentifier(BAZ))
+                    .withChild(ImmutableNodes.leafNode(XYZZY_LEAF, "xyzzy"))
+                    .build())
+                .build());
+        });
+        assertEquals("Node (foo)baz is missing mandatory descendant "
+            + "/AugmentationIdentifier{childNames=[(foo)xyzzy-augment]}/(foo)xyzzy-augment",
+            ex.getMessage());
+
+    }
+
+    private IllegalArgumentException assertFailsReady(final Consumer<DataTreeModification> operation) {
+        return assertThrows(IllegalArgumentException.class, () -> applyOperation(operation));
+    }
+
+    private void applyOperation(final Consumer<DataTreeModification> operation)
+            throws DataValidationFailedException {
+        final DataTreeModification mod = tree.takeSnapshot().newModification();
+        operation.accept(mod);
+        mod.ready();
+        tree.commit(tree.prepare(mod));
+    }
+}