Update StmtTestUtils
[yangtools.git] / yang / yang-parser-impl / src / test / java / org / opendaylight / yangtools / yang / parser / stmt / rfc7950 / Bug6887Test.java
1 /*
2  * Copyright (c) 2017 Cisco Systems, Inc. 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
9 package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14 import static org.junit.Assert.fail;
15
16 import com.google.common.collect.ImmutableList;
17 import com.google.common.collect.Iterables;
18 import java.util.Date;
19 import java.util.List;
20 import org.junit.Test;
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.common.QNameModule;
23 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
24 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.Module;
26 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
27 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
28 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
29 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
30 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
31 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
32 import org.opendaylight.yangtools.yang.model.util.type.BitBuilder;
33 import org.opendaylight.yangtools.yang.model.util.type.EnumPairBuilder;
34 import org.opendaylight.yangtools.yang.model.util.type.InvalidBitDefinitionException;
35 import org.opendaylight.yangtools.yang.model.util.type.InvalidEnumDefinitionException;
36 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
37 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
38 import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
39
40 public class Bug6887Test {
41
42     @Test
43     public void testRestrictedEnumeration() throws Exception {
44         final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo.yang");
45         assertNotNull(schemaContext);
46
47         final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-26");
48
49         final Module foo = schemaContext.findModuleByName("foo", revision);
50         assertNotNull(foo);
51
52         final LeafSchemaNode myEnumerationLeaf = (LeafSchemaNode) foo.getDataChildByName(
53                 QName.create(foo.getQNameModule(), "my-enumeration-leaf"));
54         assertNotNull(myEnumerationLeaf);
55
56         EnumTypeDefinition enumerationType = (EnumTypeDefinition) myEnumerationLeaf.getType();
57
58         List<EnumPair> enums = enumerationType.getValues();
59         assertEquals(2, enums.size());
60         final EnumPair yellowEnum = createEnumPair("yellow", 2);
61         final EnumPair redEnum = createEnumPair("red", 3);
62         assertContainsEnums(enums, yellowEnum, redEnum);
63
64         enumerationType = enumerationType.getBaseType();
65         enums = enumerationType.getValues();
66         assertEquals(3, enums.size());
67         final EnumPair blackEnum = createEnumPair("black", 4);
68         assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
69
70         enumerationType = enumerationType.getBaseType();
71         enums = enumerationType.getValues();
72         assertEquals(4, enums.size());
73         final EnumPair whiteEnum = createEnumPair("white", 1);
74         assertContainsEnums(enums, whiteEnum, yellowEnum, redEnum, blackEnum);
75
76         final LeafSchemaNode myEnumerationLeaf2 = (LeafSchemaNode) foo.getDataChildByName(
77                 QName.create(foo.getQNameModule(), "my-enumeration-leaf-2"));
78         assertNotNull(myEnumerationLeaf2);
79
80         enumerationType = (EnumTypeDefinition) myEnumerationLeaf2.getType();
81         enums = enumerationType.getValues();
82         assertEquals(3, enums.size());
83         assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
84     }
85
86     @Test
87     public void testInvalidRestrictedEnumeration() throws Exception {
88         try {
89             StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid.yang");
90             fail("An exception should have been thrown.");
91         } catch (final ReactorException ex) {
92             final Throwable cause = ex.getCause();
93             assertTrue(cause instanceof SourceException);
94             assertTrue(cause.getMessage().startsWith("Enum 'purple' is not a subset of its base enumeration type" +
95                     " (foo?revision=2017-02-02)my-derived-enumeration-type."));
96         }
97     }
98
99     @Test
100     public void testInvalidRestrictedEnumeration2() throws Exception {
101         try {
102             StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-2.yang");
103             fail("An exception should have been thrown.");
104         } catch (final ReactorException ex) {
105             final Throwable cause = ex.getCause();
106             assertTrue(cause instanceof InvalidEnumDefinitionException);
107             assertTrue(cause.getMessage().startsWith("Enum 'magenta' is not a subset of its base enumeration type" +
108                     " (foo?revision=2017-02-02)my-base-enumeration-type."));
109         }
110     }
111
112     @Test
113     public void testInvalidRestrictedEnumeration3() throws Exception {
114         try {
115             StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-3.yang");
116             fail("An exception should have been thrown.");
117         } catch (final ReactorException ex) {
118             final Throwable cause = ex.getCause();
119             assertTrue(cause instanceof InvalidEnumDefinitionException);
120             assertTrue(cause.getMessage().startsWith("Value of enum 'red' must be the same as the value of " +
121                     "corresponding enum in the base enumeration type (foo?revision=2017-02-02)" +
122                     "my-derived-enumeration-type."));
123         }
124     }
125
126     @Test
127     public void testInvalidRestrictedEnumeration4() throws Exception {
128         try {
129             StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-4.yang");
130             fail("An exception should have been thrown.");
131         } catch (final ReactorException ex) {
132             final Throwable cause = ex.getCause();
133             assertTrue(cause instanceof InvalidEnumDefinitionException);
134             assertTrue(cause.getMessage().startsWith("Value of enum 'black' must be the same as the value of " +
135                     "corresponding enum in the base enumeration type (foo?revision=2017-02-02)" +
136                     "my-base-enumeration-type."));
137         }
138     }
139
140     @Test
141     public void testValidYang10EnumerationWithUnknownStatements() throws Exception {
142         final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-valid.yang");
143         assertNotNull(schemaContext);
144     }
145
146     @Test
147     public void testInvalidYang10RestrictedEnumeration() throws Exception {
148         try {
149             StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-invalid.yang");
150             fail("An exception should have been thrown.");
151         } catch (final ReactorException ex) {
152             final Throwable cause = ex.getCause();
153             assertTrue(cause instanceof SourceException);
154             assertTrue(cause.getMessage().startsWith("Restricted enumeration type is allowed only in YANG 1.1 version."));
155         }
156     }
157
158     @Test
159     public void testInvalidYang10RestrictedEnumeration2() throws Exception {
160         try {
161             StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-invalid-2.yang");
162             fail("An exception should have been thrown.");
163         } catch (final ReactorException ex) {
164             final Throwable cause = ex.getCause();
165             assertTrue(cause instanceof SourceException);
166             assertTrue(cause.getMessage().startsWith("Restricted enumeration type is allowed only in YANG 1.1 version."));
167         }
168     }
169
170     @Test
171     public void testRestrictedBits() throws Exception {
172         final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar.yang");
173         assertNotNull(schemaContext);
174
175         final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-02-02");
176
177         final Module bar = schemaContext.findModuleByName("bar", revision);
178         assertNotNull(bar);
179
180         final LeafSchemaNode myBitsLeaf = (LeafSchemaNode) bar.getDataChildByName(
181                 QName.create(bar.getQNameModule(), "my-bits-leaf"));
182         assertNotNull(myBitsLeaf);
183
184         BitsTypeDefinition bitsType = (BitsTypeDefinition) myBitsLeaf.getType();
185
186         List<Bit> bits = bitsType.getBits();
187         assertEquals(2, bits.size());
188         Bit bitB = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-bits-leaf",
189                 "my-derived-bits-type", "bit-b")), 2);
190         Bit bitC = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-bits-leaf",
191                 "my-derived-bits-type", "bit-c")), 3);
192         assertContainsBits(bits, bitB, bitC);
193
194         bitsType = bitsType.getBaseType();
195         bits = bitsType.getBits();
196         assertEquals(3, bits.size());
197         bitB = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-derived-bits-type",
198                 "my-base-bits-type", "bit-b")), 2);
199         bitC = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-derived-bits-type",
200                 "my-base-bits-type", "bit-c")), 3);
201         Bit bitD = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-derived-bits-type",
202                 "my-base-bits-type", "bit-d")), 4);
203         assertContainsBits(bits, bitB, bitC, bitD);
204
205         bitsType = bitsType.getBaseType();
206         bits = bitsType.getBits();
207         assertEquals(4, bits.size());
208         Bit bitA = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-base-bits-type",
209                 "bits", "bit-a")), 1);
210         bitB = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-base-bits-type",
211                 "bits", "bit-b")), 2);
212         bitC = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-base-bits-type",
213                 "bits", "bit-c")), 3);
214         bitD = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-base-bits-type",
215                 "bits", "bit-d")), 4);
216         assertContainsBits(bits, bitA, bitB, bitC, bitD);
217
218         final LeafSchemaNode myBitsLeaf2 = (LeafSchemaNode) bar.getDataChildByName(
219                 QName.create(bar.getQNameModule(), "my-bits-leaf-2"));
220         assertNotNull(myBitsLeaf2);
221
222         bitsType = (BitsTypeDefinition) myBitsLeaf2.getType();
223         bits = bitsType.getBits();
224         assertEquals(3, bits.size());
225         bitB = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-derived-bits-type",
226                 "my-base-bits-type", "bit-b")), 2);
227         bitC = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-derived-bits-type",
228                 "my-base-bits-type", "bit-c")), 3);
229         bitD = createBit(createSchemaPath(true, bar.getQNameModule(), ImmutableList.of("my-derived-bits-type",
230                 "my-base-bits-type", "bit-d")), 4);
231         assertContainsBits(bits, bitB, bitC, bitD);
232     }
233
234     @Test
235     public void testInvalidRestrictedBits() throws Exception {
236         try {
237             StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid.yang");
238             fail("An exception should have been thrown.");
239         } catch (final ReactorException ex) {
240             final Throwable cause = ex.getCause();
241             assertTrue(cause instanceof SourceException);
242             assertTrue(cause.getMessage().startsWith("Bit 'bit-w' is not a subset of its base bits type" +
243                     " (bar?revision=2017-02-02)my-derived-bits-type."));
244         }
245     }
246
247     @Test
248     public void testInvalidRestrictedBits2() throws Exception {
249         try {
250             StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-2.yang");
251             fail("An exception should have been thrown.");
252         } catch (final ReactorException ex) {
253             final Throwable cause = ex.getCause();
254             assertTrue(cause instanceof InvalidBitDefinitionException);
255             assertTrue(cause.getMessage().startsWith("Bit 'bit-x' is not a subset of its base bits type" +
256                     " (bar?revision=2017-02-02)my-base-bits-type."));
257         }
258     }
259
260     @Test
261     public void testInvalidRestrictedBits3() throws Exception {
262         try {
263             StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-3.yang");
264             fail("An exception should have been thrown.");
265         } catch (final ReactorException ex) {
266             final Throwable cause = ex.getCause();
267             assertTrue(cause instanceof InvalidBitDefinitionException);
268             assertTrue(cause.getMessage().startsWith("Position of bit 'bit-c' must be the same as the position of " +
269                     "corresponding bit in the base bits type (bar?revision=2017-02-02)my-derived-bits-type."));
270         }
271     }
272
273     @Test
274     public void testInvalidRestrictedBits4() throws Exception {
275         try {
276             StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-4.yang");
277             fail("An exception should have been thrown.");
278         } catch (final ReactorException ex) {
279             final Throwable cause = ex.getCause();
280             assertTrue(cause instanceof InvalidBitDefinitionException);
281             assertTrue(cause.getMessage().startsWith("Position of bit 'bit-d' must be the same as the position of " +
282                     "corresponding bit in the base bits type (bar?revision=2017-02-02)my-base-bits-type."));
283         }
284     }
285
286     @Test
287     public void testValidYang10BitsWithUnknownStatements() throws Exception {
288         final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-valid.yang");
289         assertNotNull(schemaContext);
290     }
291
292     @Test
293     public void testInvalidYang10RestrictedBits() throws Exception {
294         try {
295             StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-invalid.yang");
296             fail("An exception should have been thrown.");
297         } catch (final ReactorException ex) {
298             final Throwable cause = ex.getCause();
299             assertTrue(cause instanceof SourceException);
300             assertTrue(cause.getMessage().startsWith("Restricted bits type is allowed only in YANG 1.1 version."));
301         }
302     }
303
304     @Test
305     public void testInvalidYang10RestrictedBits2() throws Exception {
306         try {
307             StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-invalid-2.yang");
308             fail("An exception should have been thrown.");
309         } catch (final ReactorException ex) {
310             final Throwable cause = ex.getCause();
311             assertTrue(cause instanceof SourceException);
312             assertTrue(cause.getMessage().startsWith("Restricted bits type is allowed only in YANG 1.1 version."));
313         }
314     }
315
316     private static EnumPair createEnumPair(final String name, final int value) {
317         return EnumPairBuilder.create(name, value).build();
318     }
319
320     private static void assertContainsEnums(final List<EnumPair> enumList, final EnumPair... enumPairs) {
321         for (final EnumPair enumPair : enumPairs) {
322             assertTrue(enumList.contains(enumPair));
323         }
324     }
325
326     private static Bit createBit(final SchemaPath path, final long position) {
327         return BitBuilder.create(path, position).build();
328     }
329
330     private static void assertContainsBits(final List<Bit> bitList, final Bit... bits) {
331         for (final Bit bit : bits) {
332             assertTrue(bitList.contains(bit));
333         }
334     }
335
336     private static SchemaPath createSchemaPath(final boolean absolute, final QNameModule qNameModule,
337             final Iterable<String> localNames) {
338         final Iterable<QName> qNames = Iterables.transform(localNames,
339                 localName -> QName.create(qNameModule, localName));
340         return SchemaPath.create(qNames, true);
341     }
342 }