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.ri.type.BitBuilder;
32 import org.opendaylight.yangtools.yang.model.ri.type.EnumPairBuilder;
33 import org.opendaylight.yangtools.yang.model.ri.type.InvalidBitDefinitionException;
34 import org.opendaylight.yangtools.yang.model.ri.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"));
50 EnumTypeDefinition enumerationType = (EnumTypeDefinition) myEnumerationLeaf.getType();
52 List<EnumPair> enums = enumerationType.getValues();
53 assertEquals(2, enums.size());
54 final EnumPair yellowEnum = createEnumPair("yellow", 2);
55 final EnumPair redEnum = createEnumPair("red", 3);
56 assertContainsEnums(enums, yellowEnum, redEnum);
58 enumerationType = enumerationType.getBaseType();
59 enums = enumerationType.getValues();
60 assertEquals(3, enums.size());
61 final EnumPair blackEnum = createEnumPair("black", 4);
62 assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
64 enumerationType = enumerationType.getBaseType();
65 enums = enumerationType.getValues();
66 assertEquals(4, enums.size());
67 final EnumPair whiteEnum = createEnumPair("white", 1);
68 assertContainsEnums(enums, whiteEnum, yellowEnum, redEnum, blackEnum);
70 final LeafSchemaNode myEnumerationLeaf2 = (LeafSchemaNode) foo.getDataChildByName(
71 QName.create(foo.getQNameModule(), "my-enumeration-leaf-2"));
73 enumerationType = (EnumTypeDefinition) myEnumerationLeaf2.getType();
74 enums = enumerationType.getValues();
75 assertEquals(3, enums.size());
76 assertContainsEnums(enums, yellowEnum, redEnum, blackEnum);
80 public void testInvalidRestrictedEnumeration() {
81 final ReactorException ex = assertThrows(ReactorException.class,
82 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid.yang"));
83 final Throwable cause = ex.getCause();
84 assertThat(cause, instanceOf(SourceException.class));
85 assertThat(cause.getMessage(), startsWith("Enum 'purple' is not a subset of its base enumeration type "
86 + "(foo?revision=2017-02-02)my-derived-enumeration-type."));
90 public void testInvalidRestrictedEnumeration2() {
91 final ReactorException ex = assertThrows(ReactorException.class,
92 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-2.yang"));
93 final Throwable cause = ex.getCause();
94 assertThat(cause, instanceOf(InvalidEnumDefinitionException.class));
95 assertThat(cause.getMessage(), startsWith("Enum 'magenta' is not a subset of its base enumeration type "
96 + "(foo?revision=2017-02-02)my-base-enumeration-type."));
100 public void testInvalidRestrictedEnumeration3() {
101 final ReactorException ex = assertThrows(ReactorException.class,
102 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-3.yang"));
103 final Throwable cause = ex.getCause();
104 assertThat(cause, instanceOf(InvalidEnumDefinitionException.class));
105 assertThat(cause.getMessage(), startsWith("Value of enum 'red' must be the same as the value of "
106 + "corresponding enum in the base enumeration type (foo?revision=2017-02-02)"
107 + "my-derived-enumeration-type."));
111 public void testInvalidRestrictedEnumeration4() {
112 final ReactorException ex = assertThrows(ReactorException.class,
113 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo-invalid-4.yang"));
114 final Throwable cause = ex.getCause();
115 assertThat(cause, instanceOf(InvalidEnumDefinitionException.class));
116 assertThat(cause.getMessage(), startsWith("Value of enum 'black' must be the same as the value of "
117 + "corresponding enum in the base enumeration type (foo?revision=2017-02-02)"
118 + "my-base-enumeration-type."));
122 public void testValidYang10EnumerationWithUnknownStatements() throws Exception {
123 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-valid.yang");
124 assertNotNull(schemaContext);
128 public void testInvalidYang10RestrictedEnumeration() {
129 final ReactorException ex = assertThrows(ReactorException.class,
130 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-invalid.yang"));
131 final Throwable cause = ex.getCause();
132 assertThat(cause, instanceOf(SourceException.class));
133 assertThat(cause.getMessage(), startsWith("Restricted enumeration type is not allowed in YANG version 1 [at "));
137 public void testInvalidYang10RestrictedEnumeration2() {
138 final ReactorException ex = assertThrows(ReactorException.class,
139 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/foo10-invalid-2.yang"));
140 final Throwable cause = ex.getCause();
141 assertThat(cause, instanceOf(SourceException.class));
142 assertThat(cause.getMessage(), startsWith("Restricted enumeration type is not allowed in YANG version 1 [at "));
146 public void testRestrictedBits() throws Exception {
147 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar.yang");
148 assertNotNull(schemaContext);
150 final Module bar = schemaContext.findModule("bar", Revision.of("2017-02-02")).get();
151 final LeafSchemaNode myBitsLeaf = (LeafSchemaNode) bar.getDataChildByName(
152 QName.create(bar.getQNameModule(), "my-bits-leaf"));
154 BitsTypeDefinition bitsType = (BitsTypeDefinition) myBitsLeaf.getType();
156 Collection<? extends Bit> bits = bitsType.getBits();
157 assertEquals(2, bits.size());
158 Bit bitB = createBit("bit-b", 2);
159 Bit bitC = createBit("bit-c", 3);
160 assertContainsBits(bits, bitB, bitC);
162 bitsType = bitsType.getBaseType();
163 bits = bitsType.getBits();
164 assertEquals(3, bits.size());
165 bitB = createBit("bit-b", 2);
166 bitC = createBit("bit-c", 3);
167 Bit bitD = createBit("bit-d", 4);
168 assertContainsBits(bits, bitB, bitC, bitD);
170 bitsType = bitsType.getBaseType();
171 bits = bitsType.getBits();
172 assertEquals(4, bits.size());
173 final Bit bitA = createBit("bit-a", 1);
174 bitB = createBit("bit-b", 2);
175 bitC = createBit("bit-c", 3);
176 bitD = createBit("bit-d", 4);
177 assertContainsBits(bits, bitA, bitB, bitC, bitD);
179 final LeafSchemaNode myBitsLeaf2 = (LeafSchemaNode) bar.getDataChildByName(
180 QName.create(bar.getQNameModule(), "my-bits-leaf-2"));
182 bitsType = (BitsTypeDefinition) myBitsLeaf2.getType();
183 bits = bitsType.getBits();
184 assertEquals(3, bits.size());
185 bitB = createBit("bit-b", 2);
186 bitC = createBit("bit-c", 3);
187 bitD = createBit("bit-d", 4);
188 assertContainsBits(bits, bitB, bitC, bitD);
192 public void testInvalidRestrictedBits() {
193 final ReactorException ex = assertThrows(ReactorException.class,
194 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid.yang"));
195 final Throwable cause = ex.getCause();
196 assertThat(cause, instanceOf(SourceException.class));
197 assertThat(cause.getMessage(), startsWith("Bit 'bit-w' is not a subset of its base bits type "
198 + "(bar?revision=2017-02-02)my-derived-bits-type."));
202 public void testInvalidRestrictedBits2() {
203 final ReactorException ex = assertThrows(ReactorException.class,
204 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-2.yang"));
205 final Throwable cause = ex.getCause();
206 assertThat(cause, instanceOf(InvalidBitDefinitionException.class));
207 assertThat(cause.getMessage(), startsWith("Bit 'bit-x' is not a subset of its base bits type "
208 + "(bar?revision=2017-02-02)my-base-bits-type."));
212 public void testInvalidRestrictedBits3() {
213 final ReactorException ex = assertThrows(ReactorException.class,
214 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-3.yang"));
215 final Throwable cause = ex.getCause();
216 assertThat(cause, instanceOf(InvalidBitDefinitionException.class));
217 assertThat(cause.getMessage(), startsWith("Position of bit 'bit-c' must be the same as the position of "
218 + "corresponding bit in the base bits type (bar?revision=2017-02-02)my-derived-bits-type."));
222 public void testInvalidRestrictedBits4() {
223 final ReactorException ex = assertThrows(ReactorException.class,
224 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar-invalid-4.yang"));
225 final Throwable cause = ex.getCause();
226 assertThat(cause, instanceOf(InvalidBitDefinitionException.class));
227 assertThat(cause.getMessage(), startsWith("Position of bit 'bit-d' must be the same as the position of "
228 + "corresponding bit in the base bits type (bar?revision=2017-02-02)my-base-bits-type."));
232 public void testValidYang10BitsWithUnknownStatements() throws Exception {
233 final SchemaContext schemaContext = StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-valid.yang");
234 assertNotNull(schemaContext);
238 public void testInvalidYang10RestrictedBits() {
239 final ReactorException ex = assertThrows(ReactorException.class,
240 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-invalid.yang"));
241 final Throwable cause = ex.getCause();
242 assertThat(cause, instanceOf(SourceException.class));
243 assertThat(cause.getMessage(), startsWith("Restricted bits type is not allowed in YANG version 1 [at "));
247 public void testInvalidYang10RestrictedBits2() {
248 final ReactorException ex = assertThrows(ReactorException.class,
249 () -> StmtTestUtils.parseYangSource("/rfc7950/bug6887/bar10-invalid-2.yang"));
250 final Throwable cause = ex.getCause();
251 assertThat(cause, instanceOf(SourceException.class));
252 assertThat(cause.getMessage(), startsWith("Restricted bits type is not allowed in YANG version 1 [at "));
255 private static EnumPair createEnumPair(final String name, final int value) {
256 return EnumPairBuilder.create(name, value).build();
259 private static void assertContainsEnums(final List<EnumPair> enumList, final EnumPair... enumPairs) {
260 for (final EnumPair enumPair : enumPairs) {
261 assertTrue(enumList.contains(enumPair));
265 private static Bit createBit(final String name, final long position) {
266 return BitBuilder.create(name, Uint32.valueOf(position)).build();
269 private static void assertContainsBits(final Collection<? extends Bit> bitList, final Bit... bits) {
270 for (final Bit bit : bits) {
271 assertTrue(bitList.contains(bit));