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
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.fail;
12 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.containerBuilder;
13 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafBuilder;
14 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.leafSetBuilder;
15 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.mapBuilder;
16 import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.mapEntryBuilder;
17
18 import com.google.common.collect.ImmutableMap;
19 import org.junit.AfterClass;
20 import org.junit.Before;
21 import org.junit.BeforeClass;
22 import org.junit.Test;
23 import org.opendaylight.yangtools.yang.common.QName;
24 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
27 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
28 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
29 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree;
30 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeConfiguration;
31 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification;
32 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
33 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
34
35 public class YT776Test {
36     private static final QName MODULE = QName.create("yt776", "yt776");
37     private static final NodeIdentifier BOX = new NodeIdentifier(QName.create(MODULE, "box"));
38     private static final QName OBJECT = QName.create(MODULE, "object");
39     private static final QName OBJECT_ID = QName.create(MODULE, "object-id");
40     private static final NodeIdentifier OBJECT_LIST = new NodeIdentifier(QName.create(MODULE, "object"));
41     private static final NodeIdentifierWithPredicates OBJECT_ITEM = new NodeIdentifierWithPredicates(OBJECT,
42         ImmutableMap.of(OBJECT_ID, "1"));
43     private static final LeafNode<?> OBJECT_ID_LEAF = leafBuilder().withNodeIdentifier(new NodeIdentifier(OBJECT_ID))
44             .withValue("1").build();
45     private static final NodeIdentifier ATTRIBUTES = new NodeIdentifier(QName.create(MODULE, "attributes"));
46
47     private static SchemaContext SCHEMA_CONTEXT;
48
49     private DataTree dataTree;
50
51     @BeforeClass
52     public static void beforeClass() {
53         SCHEMA_CONTEXT = TestModel.createTestContext("/yt776/yt776.yang");
54     }
55
56     @AfterClass
57     public static void afterClass() {
58         SCHEMA_CONTEXT = null;
59     }
60
61     @Before
62     public void init() {
63         dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, SCHEMA_CONTEXT);
64     }
65
66     @Test
67     public void testNoAttributes() {
68         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
69         mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
70             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
71                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
72                     .withChild(OBJECT_ID_LEAF)
73                     .build())
74                 .build())
75             .build());
76
77         try {
78             mod.ready();
79             fail("Should fail with IAE");
80         } catch (IllegalArgumentException e) {
81             // FIXME: This is actually mandatory leaf enforcer kicking in: attributes have to be present. This is
82             //        most probably not what we want.
83             assertEquals("Node (yt776)object[{(yt776)object-id=1}] is missing mandatory descendant /(yt776)attributes",
84                 e.getMessage());
85         }
86     }
87
88     @Test
89     public void testEmptyAttributes() throws DataValidationFailedException {
90         final DataTreeModification mod = write(containerBuilder().withNodeIdentifier(BOX)
91             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
92                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
93                     .withChild(OBJECT_ID_LEAF)
94                     .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES).build())
95                     .build())
96                 .build())
97             .build());
98
99         try {
100             mod.ready();
101             fail("Should fail with IAE");
102         } catch (IllegalArgumentException e) {
103             assertEquals("Node (yt776)attributes does not have enough elements (0), needs at least 1", e.getMessage());
104         }
105     }
106
107     @Test
108     public void testOneAttribute() throws DataValidationFailedException {
109         writeAndCommit(containerBuilder().withNodeIdentifier(BOX)
110             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
111                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
112                     .withChild(OBJECT_ID_LEAF)
113                     .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
114                         .withChildValue("object1")
115                         .build())
116                     .build())
117                 .build())
118             .build());
119     }
120
121     @Test
122     public void testTwoAttributes() throws DataValidationFailedException {
123         writeAndCommit(containerBuilder().withNodeIdentifier(BOX)
124             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
125                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
126                     .withChild(OBJECT_ID_LEAF)
127                     .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
128                         .withChildValue("object1")
129                         .withChildValue("object2")
130                         .build())
131                     .build())
132                 .build())
133             .build());
134     }
135
136     @Test
137     public void testThreeAttributes() throws DataValidationFailedException {
138         final DataTreeModification mod = write(containerBuilder().withNodeIdentifier(BOX)
139             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
140                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
141                     .withChild(OBJECT_ID_LEAF)
142                     .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
143                         .withChildValue("object1")
144                         .withChildValue("object2")
145                         .withChildValue("object3")
146                         .build())
147                     .build())
148                 .build())
149             .build());
150
151         try {
152             mod.ready();
153             fail("Should fail with IAE");
154         } catch (IllegalArgumentException e) {
155             assertEquals("Node (yt776)attributes has too many elements (3), can have at most 2", e.getMessage());
156         }
157     }
158
159     @Test
160     public void testEmptyAndMergeOne() throws DataValidationFailedException {
161         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
162         mod.write(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
163             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
164                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
165                     .withChild(OBJECT_ID_LEAF)
166                     .build())
167                 .build())
168             .build());
169         mod.merge(YangInstanceIdentifier.create(BOX), containerBuilder().withNodeIdentifier(BOX)
170             .withChild(mapBuilder().withNodeIdentifier(OBJECT_LIST)
171                 .addChild(mapEntryBuilder().withNodeIdentifier(OBJECT_ITEM)
172                     .withChild(OBJECT_ID_LEAF)
173                     .withChild(leafSetBuilder().withNodeIdentifier(ATTRIBUTES)
174                         .withChildValue("object1")
175                         .build())
176                     .build())
177                 .build())
178             .build());
179
180         commit(mod);
181     }
182
183     private DataTreeModification write(final ContainerNode data) throws DataValidationFailedException {
184         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
185         mod.write(YangInstanceIdentifier.create(BOX), data);
186         return mod;
187     }
188
189     private void writeAndCommit(final ContainerNode data) throws DataValidationFailedException {
190         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
191         mod.write(YangInstanceIdentifier.create(BOX), data);
192         commit(mod);
193     }
194
195     private void commit(final DataTreeModification mod) throws DataValidationFailedException {
196         mod.ready();
197         dataTree.validate(mod);
198         dataTree.commit(dataTree.prepare(mod));
199     }
200 }