2 * Copyright (c) 2017 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
9 package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
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;
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;
40 public class Bug6887Test {
43 public void testRestrictedEnumeration() throws Exception {
44 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo.yang");
45 assertNotNull(schemaContext);
47 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-01-26");
49 final Module foo = schemaContext.findModuleByName("foo", revision);
52 final LeafSchemaNode myEnumerationLeaf = (LeafSchemaNode) foo.getDataChildByName(
53 QName.create(foo.getQNameModule(), "my-enumeration-leaf"));
54 assertNotNull(myEnumerationLeaf);
56 EnumTypeDefinition enumerationType = (EnumTypeDefinition) myEnumerationLeaf.getType();
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);
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);
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);
76 final LeafSchemaNode myEnumerationLeaf2 = (LeafSchemaNode) foo.getDataChildByName(
77 QName.create(foo.getQNameModule(), "my-enumeration-leaf-2"));
78 assertNotNull(myEnumerationLeaf2);
80 enumerationType = (EnumTypeDefinition) myEnumerationLeaf2.getType();
81 enums = enumerationType.getValues();
82 assertEquals(3, enums.size());
83 assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
87 public void testInvalidRestrictedEnumeration() throws Exception {
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."));
100 public void testInvalidRestrictedEnumeration2() throws Exception {
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."));
113 public void testInvalidRestrictedEnumeration3() throws Exception {
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."));
127 public void testInvalidRestrictedEnumeration4() throws Exception {
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."));
141 public void testValidYang10EnumerationWithUnknownStatements() throws Exception {
142 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-valid.yang");
143 assertNotNull(schemaContext);
147 public void testInvalidYang10RestrictedEnumeration() throws Exception {
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."));
159 public void testInvalidYang10RestrictedEnumeration2() throws Exception {
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."));
171 public void testRestrictedBits() throws Exception {
172 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar.yang");
173 assertNotNull(schemaContext);
175 final Date revision = SimpleDateFormatUtil.getRevisionFormat().parse("2017-02-02");
177 final Module bar = schemaContext.findModuleByName("bar", revision);
180 final LeafSchemaNode myBitsLeaf = (LeafSchemaNode) bar.getDataChildByName(
181 QName.create(bar.getQNameModule(), "my-bits-leaf"));
182 assertNotNull(myBitsLeaf);
184 BitsTypeDefinition bitsType = (BitsTypeDefinition) myBitsLeaf.getType();
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);
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);
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);
218 final LeafSchemaNode myBitsLeaf2 = (LeafSchemaNode) bar.getDataChildByName(
219 QName.create(bar.getQNameModule(), "my-bits-leaf-2"));
220 assertNotNull(myBitsLeaf2);
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);
235 public void testInvalidRestrictedBits() throws Exception {
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."));
248 public void testInvalidRestrictedBits2() throws Exception {
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."));
261 public void testInvalidRestrictedBits3() throws Exception {
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."));
274 public void testInvalidRestrictedBits4() throws Exception {
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."));
287 public void testValidYang10BitsWithUnknownStatements() throws Exception {
288 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-valid.yang");
289 assertNotNull(schemaContext);
293 public void testInvalidYang10RestrictedBits() throws Exception {
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."));
305 public void testInvalidYang10RestrictedBits2() throws Exception {
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."));
316 private static EnumPair createEnumPair(final String name, final int value) {
317 return EnumPairBuilder.create(name, value).build();
320 private static void assertContainsEnums(final List<EnumPair> enumList, final EnumPair... enumPairs) {
321 for (final EnumPair enumPair : enumPairs) {
322 assertTrue(enumList.contains(enumPair));
326 private static Bit createBit(final SchemaPath path, final long position) {
327 return BitBuilder.create(path, position).build();
330 private static void assertContainsBits(final List<Bit> bitList, final Bit... bits) {
331 for (final Bit bit : bits) {
332 assertTrue(bitList.contains(bit));
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);