Fix min/max validation inside written value
[yangtools.git] / yang / yang-data-impl / src / test / java / org / opendaylight / yangtools / yang / data / impl / schema / tree / YT776Test.java
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/YT776Test.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/YT776Test.java
new file mode 100644 (file)
index 0000000..512baa5
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2018 Pantheon Technologies, 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.fail;
+import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containerBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafSetBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.mapBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.mapEntryBuilder;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.AfterClass;
+import org.junit.Before;
+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.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+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.model.api.SchemaContext;
+
+public class YT776Test {
+    private static final QName MODULE = QName.create("yt776", "yt776");
+    private static final NodeIdentifier BOX = new NodeIdentifier(QName.create(MODULE, "box"));
+    private static final QName OBJECT = QName.create(MODULE, "object");
+    private static final QName OBJECT_ID = QName.create(MODULE, "object-id");
+    private static final NodeIdentifier OBJECT_LIST = new NodeIdentifier(QName.create(MODULE, "object"));
+    private static final NodeIdentifierWithPredicates OBJECT_ITEM = new NodeIdentifierWithPredicates(OBJECT,
+        ImmutableMap.of(OBJECT_ID, "1"));
+    private static final LeafNode<?> OBJECT_ID_LEAF = leafBuilder().withNodeIdentifier(new NodeIdentifier(OBJECT_ID))
+            .withValue("1").build();
+    private static final NodeIdentifier ATTRIBUTES = new NodeIdentifier(QName.create(MODULE, "attributes"));
+
+    private static SchemaContext SCHEMA_CONTEXT;
+
+    private DataTree dataTree;
+
+    @BeforeClass
+    public static void beforeClass() {
+        SCHEMA_CONTEXT = TestModel.createTestContext("/yt776/yt776.yang");
+    }
+
+    @AfterClass
+    public static void afterClass() {
+        SCHEMA_CONTEXT = null;
+    }
+
+    @Before
+    public void init() {
+        dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, SCHEMA_CONTEXT);
+    }
+
+    @Test
+    public void testNoAttributes() {
+        final DataTreeModification mod = dataTree.takeSnapshot().newModification();
+        mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .build())
+                .build())
+            .build());
+
+        try {
+            mod.ready();
+            fail("Should fail with IAE");
+        } catch (IllegalArgumentException e) {
+            // FIXME: This is actually mandatory leaf enforcer kicking in: attributes have to be present. This is
+            //        most probably not what we want.
+            assertEquals("Node (yt776)object[{(yt776)object-id=1}] is missing mandatory descendant /(yt776)attributes",
+                e.getMessage());
+        }
+    }
+
+    @Test
+    public void testEmptyAttributes() throws DataValidationFailedException {
+        final DataTreeModification mod = write(containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES).build())
+                    .build())
+                .build())
+            .build());
+
+        try {
+            mod.ready();
+            fail("Should fail with IAE");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Node (yt776)attributes does not have enough elements (0), needs at least 1", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testOneAttribute() throws DataValidationFailedException {
+        writeAndCommit(containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
+                        .withChildValue("object1")
+                        .build())
+                    .build())
+                .build())
+            .build());
+    }
+
+    @Test
+    public void testTwoAttributes() throws DataValidationFailedException {
+        writeAndCommit(containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
+                        .withChildValue("object1")
+                        .withChildValue("object2")
+                        .build())
+                    .build())
+                .build())
+            .build());
+    }
+
+    @Test
+    public void testThreeAttributes() throws DataValidationFailedException {
+        final DataTreeModification mod = write(containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
+                        .withChildValue("object1")
+                        .withChildValue("object2")
+                        .withChildValue("object3")
+                        .build())
+                    .build())
+                .build())
+            .build());
+
+        try {
+            mod.ready();
+            fail("Should fail with IAE");
+        } catch (IllegalArgumentException e) {
+            assertEquals("Node (yt776)attributes has too many elements (3), can have at most 2", e.getMessage());
+        }
+    }
+
+    @Test
+    public void testEmptyAndMergeOne() throws DataValidationFailedException {
+        final DataTreeModification mod = dataTree.takeSnapshot().newModification();
+        mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .build())
+                .build())
+            .build());
+        mod.merge(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
+            .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
+                .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
+                    .withChild(OBJECT_ID_LEAF)
+                    .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
+                        .withChildValue("object1")
+                        .build())
+                    .build())
+                .build())
+            .build());
+
+        commit(mod);
+    }
+
+    private DataTreeModification write(final ContainerNode data) throws DataValidationFailedException {
+        final DataTreeModification mod = dataTree.takeSnapshot().newModification();
+        mod.write(YangInstanceIdentifier.create(BOX), data);
+        return mod;
+    }
+
+    private void writeAndCommit(final ContainerNode data) throws DataValidationFailedException {
+        final DataTreeModification mod = dataTree.takeSnapshot().newModification();
+        mod.write(YangInstanceIdentifier.create(BOX), data);
+        commit(mod);
+    }
+
+    private void commit(final DataTreeModification mod) throws DataValidationFailedException {
+        mod.ready();
+        dataTree.validate(mod);
+        dataTree.commit(dataTree.prepare(mod));
+    }
+}