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
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc7950;
10 import static org.hamcrest.CoreMatchers.instanceOf;
11 import static org.hamcrest.CoreMatchers.startsWith;
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertNotNull;
15 import static org.junit.Assert.assertThrows;
16 import static org.junit.Assert.assertTrue;
18 import java.util.Collection;
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.Revision;
23 import org.opendaylight.yangtools.yang.common.Uint32;
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.type.BitsTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
29 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
30 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
31 import org.opendaylight.yangtools.yang.model.util.type.BitBuilder;
32 import org.opendaylight.yangtools.yang.model.util.type.EnumPairBuilder;
33 import org.opendaylight.yangtools.yang.model.util.type.InvalidBitDefinitionException;
34 import org.opendaylight.yangtools.yang.model.util.type.InvalidEnumDefinitionException;
35 import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
36 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
37 import org.opendaylight.yangtools.yang.stmt.StmtTestUtils;
39 public class Bug6887Test {
42 public void testRestrictedEnumeration() throws Exception {
43 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo.yang");
44 assertNotNull(schemaContext);
46 final Module foo = schemaContext.findModule("foo", Revision.of("2017-01-26")).get();
47 final LeafSchemaNode myEnumerationLeaf = (LeafSchemaNode) foo.getDataChildByName(
48 QName.create(foo.getQNameModule(), "my-enumeration-leaf"));
49 assertNotNull(myEnumerationLeaf);
51 EnumTypeDefinition enumerationType = (EnumTypeDefinition) myEnumerationLeaf.getType();
53 List<EnumPair> enums = enumerationType.getValues();
54 assertEquals(2, enums.size());
55 final EnumPair yellowEnum = createEnumPair("yellow", 2);
56 final EnumPair redEnum = createEnumPair("red", 3);
57 assertContainsEnums(enums, yellowEnum, redEnum);
59 enumerationType = enumerationType.getBaseType();
60 enums = enumerationType.getValues();
61 assertEquals(3, enums.size());
62 final EnumPair blackEnum = createEnumPair("black", 4);
63 assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
65 enumerationType = enumerationType.getBaseType();
66 enums = enumerationType.getValues();
67 assertEquals(4, enums.size());
68 final EnumPair whiteEnum = createEnumPair("white", 1);
69 assertContainsEnums(enums, whiteEnum, yellowEnum, redEnum, blackEnum);
71 final LeafSchemaNode myEnumerationLeaf2 = (LeafSchemaNode) foo.getDataChildByName(
72 QName.create(foo.getQNameModule(), "my-enumeration-leaf-2"));
73 assertNotNull(myEnumerationLeaf2);
75 enumerationType = (EnumTypeDefinition) myEnumerationLeaf2.getType();
76 enums = enumerationType.getValues();
77 assertEquals(3, enums.size());
78 assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
82 public void testInvalidRestrictedEnumeration() {
83 final ReactorException ex = assertThrows(ReactorException.class,
84 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid.yang"));
85 final Throwable cause = ex.getCause();
86 assertThat(cause, instanceOf(SourceException.class));
87 assertThat(cause.getMessage(), startsWith("Enum 'purple' is not a subset of its base enumeration type "
88 + "(foo?revision=2017-02-02)my-derived-enumeration-type."));
92 public void testInvalidRestrictedEnumeration2() {
93 final ReactorException ex = assertThrows(ReactorException.class,
94 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-2.yang"));
95 final Throwable cause = ex.getCause();
96 assertThat(cause, instanceOf(InvalidEnumDefinitionException.class));
97 assertThat(cause.getMessage(), startsWith("Enum 'magenta' is not a subset of its base enumeration type "
98 + "(foo?revision=2017-02-02)my-base-enumeration-type."));
102 public void testInvalidRestrictedEnumeration3() {
103 final ReactorException ex = assertThrows(ReactorException.class,
104 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-3.yang"));
105 final Throwable cause = ex.getCause();
106 assertThat(cause, instanceOf(InvalidEnumDefinitionException.class));
107 assertThat(cause.getMessage(), startsWith("Value of enum 'red' must be the same as the value of "
108 + "corresponding enum in the base enumeration type (foo?revision=2017-02-02)"
109 + "my-derived-enumeration-type."));
113 public void testInvalidRestrictedEnumeration4() {
114 final ReactorException ex = assertThrows(ReactorException.class,
115 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-4.yang"));
116 final Throwable cause = ex.getCause();
117 assertThat(cause, instanceOf(InvalidEnumDefinitionException.class));
118 assertThat(cause.getMessage(), startsWith("Value of enum 'black' must be the same as the value of "
119 + "corresponding enum in the base enumeration type (foo?revision=2017-02-02)"
120 + "my-base-enumeration-type."));
124 public void testValidYang10EnumerationWithUnknownStatements() throws Exception {
125 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-valid.yang");
126 assertNotNull(schemaContext);
130 public void testInvalidYang10RestrictedEnumeration() {
131 final ReactorException ex = assertThrows(ReactorException.class,
132 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-invalid.yang"));
133 final Throwable cause = ex.getCause();
134 assertThat(cause, instanceOf(SourceException.class));
135 assertThat(cause.getMessage(), startsWith("Restricted enumeration type is not allowed in YANG version 1 [at "));
139 public void testInvalidYang10RestrictedEnumeration2() {
140 final ReactorException ex = assertThrows(ReactorException.class,
141 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-invalid-2.yang"));
142 final Throwable cause = ex.getCause();
143 assertThat(cause, instanceOf(SourceException.class));
144 assertThat(cause.getMessage(), startsWith("Restricted enumeration type is not allowed in YANG version 1 [at "));
148 public void testRestrictedBits() throws Exception {
149 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar.yang");
150 assertNotNull(schemaContext);
152 final Module bar = schemaContext.findModule("bar", Revision.of("2017-02-02")).get();
153 final LeafSchemaNode myBitsLeaf = (LeafSchemaNode) bar.getDataChildByName(
154 QName.create(bar.getQNameModule(), "my-bits-leaf"));
155 assertNotNull(myBitsLeaf);
157 BitsTypeDefinition bitsType = (BitsTypeDefinition) myBitsLeaf.getType();
159 Collection<? extends Bit> bits = bitsType.getBits();
160 assertEquals(2, bits.size());
161 Bit bitB = createBit("bit-b", 2);
162 Bit bitC = createBit("bit-c", 3);
163 assertContainsBits(bits, bitB, bitC);
165 bitsType = bitsType.getBaseType();
166 bits = bitsType.getBits();
167 assertEquals(3, bits.size());
168 bitB = createBit("bit-b", 2);
169 bitC = createBit("bit-c", 3);
170 Bit bitD = createBit("bit-d", 4);
171 assertContainsBits(bits, bitB, bitC, bitD);
173 bitsType = bitsType.getBaseType();
174 bits = bitsType.getBits();
175 assertEquals(4, bits.size());
176 final Bit bitA = createBit("bit-a", 1);
177 bitB = createBit("bit-b", 2);
178 bitC = createBit("bit-c", 3);
179 bitD = createBit("bit-d", 4);
180 assertContainsBits(bits, bitA, bitB, bitC, bitD);
182 final LeafSchemaNode myBitsLeaf2 = (LeafSchemaNode) bar.getDataChildByName(
183 QName.create(bar.getQNameModule(), "my-bits-leaf-2"));
184 assertNotNull(myBitsLeaf2);
186 bitsType = (BitsTypeDefinition) myBitsLeaf2.getType();
187 bits = bitsType.getBits();
188 assertEquals(3, bits.size());
189 bitB = createBit("bit-b", 2);
190 bitC = createBit("bit-c", 3);
191 bitD = createBit("bit-d", 4);
192 assertContainsBits(bits, bitB, bitC, bitD);
196 public void testInvalidRestrictedBits() {
197 final ReactorException ex = assertThrows(ReactorException.class,
198 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid.yang"));
199 final Throwable cause = ex.getCause();
200 assertThat(cause, instanceOf(SourceException.class));
201 assertThat(cause.getMessage(), startsWith("Bit 'bit-w' is not a subset of its base bits type "
202 + "(bar?revision=2017-02-02)my-derived-bits-type."));
206 public void testInvalidRestrictedBits2() {
207 final ReactorException ex = assertThrows(ReactorException.class,
208 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-2.yang"));
209 final Throwable cause = ex.getCause();
210 assertThat(cause, instanceOf(InvalidBitDefinitionException.class));
211 assertThat(cause.getMessage(), startsWith("Bit 'bit-x' is not a subset of its base bits type "
212 + "(bar?revision=2017-02-02)my-base-bits-type."));
216 public void testInvalidRestrictedBits3() {
217 final ReactorException ex = assertThrows(ReactorException.class,
218 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-3.yang"));
219 final Throwable cause = ex.getCause();
220 assertThat(cause, instanceOf(InvalidBitDefinitionException.class));
221 assertThat(cause.getMessage(), startsWith("Position of bit 'bit-c' must be the same as the position of "
222 + "corresponding bit in the base bits type (bar?revision=2017-02-02)my-derived-bits-type."));
226 public void testInvalidRestrictedBits4() {
227 final ReactorException ex = assertThrows(ReactorException.class,
228 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-4.yang"));
229 final Throwable cause = ex.getCause();
230 assertThat(cause, instanceOf(InvalidBitDefinitionException.class));
231 assertThat(cause.getMessage(), startsWith("Position of bit 'bit-d' must be the same as the position of "
232 + "corresponding bit in the base bits type (bar?revision=2017-02-02)my-base-bits-type."));
236 public void testValidYang10BitsWithUnknownStatements() throws Exception {
237 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-valid.yang");
238 assertNotNull(schemaContext);
242 public void testInvalidYang10RestrictedBits() {
243 final ReactorException ex = assertThrows(ReactorException.class,
244 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-invalid.yang"));
245 final Throwable cause = ex.getCause();
246 assertThat(cause, instanceOf(SourceException.class));
247 assertThat(cause.getMessage(), startsWith("Restricted bits type is not allowed in YANG version 1 [at "));
251 public void testInvalidYang10RestrictedBits2() {
252 final ReactorException ex = assertThrows(ReactorException.class,
253 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-invalid-2.yang"));
254 final Throwable cause = ex.getCause();
255 assertThat(cause, instanceOf(SourceException.class));
256 assertThat(cause.getMessage(), startsWith("Restricted bits type is not allowed in YANG version 1 [at "));
259 private static EnumPair createEnumPair(final String name, final int value) {
260 return EnumPairBuilder.create(name, value).build();
263 private static void assertContainsEnums(final List<EnumPair> enumList, final EnumPair... enumPairs) {
264 for (final EnumPair enumPair : enumPairs) {
265 assertTrue(enumList.contains(enumPair));
269 private static Bit createBit(final String name, final long position) {
270 return BitBuilder.create(name, Uint32.valueOf(position)).build();
273 private static void assertContainsBits(final Collection<? extends Bit> bitList, final Bit... bits) {
274 for (final Bit bit : bits) {
275 assertTrue(bitList.contains(bit));