5271db18683776d4e4b651f060e2a0503bd40a07
[mdsal.git] / binding / mdsal-binding-generator / src / test / java / org / opendaylight / mdsal / binding / generator / impl / DefaultBindingGeneratorTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  * Copyright (c) 2021 PANTHEON.tech, s.r.o.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9 package org.opendaylight.mdsal.binding.generator.impl;
10
11 import static org.hamcrest.CoreMatchers.instanceOf;
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertFalse;
15 import static org.junit.Assert.assertSame;
16 import static org.junit.Assert.assertThrows;
17 import static org.junit.Assert.assertTrue;
18
19 import java.util.List;
20 import org.junit.AfterClass;
21 import org.junit.BeforeClass;
22 import org.junit.Test;
23 import org.junit.runner.RunWith;
24 import org.mockito.junit.MockitoJUnitRunner;
25 import org.opendaylight.mdsal.binding.model.api.Enumeration;
26 import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
27 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
28 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
29 import org.opendaylight.mdsal.binding.model.api.MethodSignature;
30 import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
31 import org.opendaylight.mdsal.binding.model.api.Type;
32 import org.opendaylight.mdsal.binding.model.ri.Types;
33 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
34 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
35
36 /**
37  * General test suite revolving around {@link DefaultBindingGenerator}. This class holds tests originally aimed at
38  * specific implementation methods, but now they really are all about integration testing.
39  *
40  * @author Lukas Sedlak
41  * @author Robert Varga
42  */
43 @RunWith(MockitoJUnitRunner.class)
44 public class DefaultBindingGeneratorTest {
45     public static final String BASE_YANG_TYPES =
46         "org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914";
47     public static final String TEST_TYPE_PROVIDER =
48         "org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912";
49     public static final String TEST_TYPE_PROVIDER_B =
50         "org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.b.model.rev140915";
51     public static final JavaTypeName CONSTRUCTION_TYPE_TEST =
52         JavaTypeName.create(TEST_TYPE_PROVIDER, "ConstructionTypeTest");
53     public static final JavaTypeName TEST_TYPE_PROVIDER_B_DATA =
54         JavaTypeName.create(TEST_TYPE_PROVIDER_B, "TestTypeProviderBData");
55     public static final JavaTypeName TEST_TYPE_PROVIDER_FOO =
56         JavaTypeName.create(TEST_TYPE_PROVIDER, "Foo");
57
58     public static EffectiveModelContext SCHEMA_CONTEXT;
59     public static List<GeneratedType> TYPES;
60
61     @BeforeClass
62     public static void beforeClass() {
63         SCHEMA_CONTEXT = YangParserTestUtils.parseYangResources(DefaultBindingGeneratorTest.class,
64             "/base-yang-types.yang", "/test-type-provider-b.yang", "/test-type-provider.yang");
65         TYPES = DefaultBindingGenerator.generateFor(SCHEMA_CONTEXT);
66     }
67
68     @AfterClass
69     public static void afterClass() {
70         SCHEMA_CONTEXT = null;
71         TYPES = null;
72     }
73
74     @Test
75     public void javaTypeForSchemaDefinitionLeafrefToEnumTypeTest() {
76         final var bData = assertGeneratedType(TEST_TYPE_PROVIDER_B_DATA);
77         final var bDataMethods = bData.getMethodDefinitions();
78         assertEquals(8, bDataMethods.size());
79
80         final var bEnumType = assertGeneratedMethod(bDataMethods, "getEnum").getReturnType();
81         assertThat(bEnumType, instanceOf(Enumeration.class));
82         assertEquals(TEST_TYPE_PROVIDER + ".Foo.ResolveDirectUseOfEnum", bEnumType.getFullyQualifiedName());
83
84         final var bEnumsType = assertGeneratedMethod(bDataMethods, "getEnums").getReturnType();
85
86         assertThat(bEnumsType, instanceOf(ParameterizedType.class));
87         final var enumsType = (ParameterizedType) bEnumsType;
88
89         assertEquals(Types.typeForClass(List.class), enumsType.getRawType());
90         final var enumsTypeArgs = enumsType.getActualTypeArguments();
91         assertEquals(1, enumsTypeArgs.length);
92         assertEquals(TEST_TYPE_PROVIDER + ".Foo.ListOfEnums", enumsTypeArgs[0].getFullyQualifiedName());
93     }
94
95     @Test
96     public void generatedTypeForExtendedDefinitionTypeWithIdentityrefBaseTypeTest() {
97         assertEquals(Types.parameterizedTypeFor(Types.CLASS, Type.of(JavaTypeName.create(TEST_TYPE_PROVIDER, "Aes"))),
98             assertGeneratedMethod(CONSTRUCTION_TYPE_TEST, "getAesIdentityrefType").getReturnType());
99     }
100
101     @Test
102     public void generatedTypeForExtendedDefinitionTypeWithLeafrefBaseTypeTest() {
103         final var type = assertGeneratedMethod(CONSTRUCTION_TYPE_TEST, "getBarId").getReturnType();
104         assertThat(type, instanceOf(GeneratedTransferObject.class));
105         final var gto = (GeneratedTransferObject) type;
106         assertEquals(JavaTypeName.create(BASE_YANG_TYPES, "YangInt16"), gto.getIdentifier());
107     }
108
109     @Test
110     public void generatedTypeForExtendedDefinitionTypeWithInnerExtendedTypeTest() {
111         assertGTO(JavaTypeName.create(TEST_TYPE_PROVIDER, "ExtendedYangInt8"));
112     }
113
114     @Test
115     public void generatedTypeForExtendedDefinitionTypeTest() {
116         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangBoolean"));
117         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangEmpty"));
118         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8"));
119         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8Restricted"));
120         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt16"));
121         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt32"));
122         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt64"));
123         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangString"));
124         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangDecimal64"));
125         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangUint8"));
126         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangUint16"));
127         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangUint32"));
128         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangUint64"));
129         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangUnion"));
130         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangBinary"));
131         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInstanceIdentifier"));
132         assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangBits"));
133         assertEnumeration(JavaTypeName.create(BASE_YANG_TYPES, "YangEnumeration"));
134     }
135
136     @Test
137     public void provideGeneratedTOBuilderForUnionTypeDefWithInnerUnionTypesTest() {
138         final var gto = assertGTO(JavaTypeName.create(TEST_TYPE_PROVIDER, "ComplexUnion"));
139         assertEquals(3, gto.getProperties().size());
140         assertEquals(List.of(), gto.getEnumerations());
141         final var enclosed = gto.getEnclosedTypes();
142         assertEquals(1, enclosed.size());
143
144         final var union1 = enclosed.get(0);
145         assertThat(union1, instanceOf(GeneratedTransferObject.class));
146         assertEquals(TEST_TYPE_PROVIDER + ".ComplexUnion.ComplexUnion$1", union1.getFullyQualifiedName());
147         assertEquals(1, union1.getProperties().size());
148         assertEquals(List.of(), union1.getEnclosedTypes());
149
150         final var enums = union1.getEnumerations();
151         assertEquals(1, enums.size());
152         assertEquals(TEST_TYPE_PROVIDER + ".ComplexUnion.ComplexUnion$1.Enumeration",
153             enums.get(0).getFullyQualifiedName());
154     }
155
156     @Test
157     public void provideGeneratedTOBuilderForUnionTypeDefWithInnerUnionAndSimpleTypeTest() {
158         final var gto = assertGTO(JavaTypeName.create(TEST_TYPE_PROVIDER, "ComplexStringIntUnion"));
159         assertEquals(2, gto.getProperties().size());
160         assertEquals(List.of(), gto.getEnumerations());
161         assertEquals(List.of(), gto.getEnclosedTypes());
162     }
163
164     @Test
165     public void javaTypeForSchemaDefinitionForExtUnionWithSimpleTypesTest() {
166         final var type = assertGeneratedMethod(
167             JavaTypeName.create(TEST_TYPE_PROVIDER, "UseOfUnions"), "getSimpleIntTypesUnion").getReturnType();
168         assertThat(type, instanceOf(GeneratedTransferObject.class));
169         assertEquals(JavaTypeName.create(BASE_YANG_TYPES, "YangUnion"), type.getIdentifier());
170     }
171
172     @Test
173     public void javaTypeForSchemaDefinitionForExtUnionWithInnerUnionAndSimpleTypeTest() {
174         final var type = assertGeneratedMethod(
175             JavaTypeName.create(TEST_TYPE_PROVIDER, "UseOfUnions"), "getComplexStringIntUnion").getReturnType();
176         assertThat(type, instanceOf(GeneratedTransferObject.class));
177         assertEquals(JavaTypeName.create(TEST_TYPE_PROVIDER, "ComplexStringIntUnion"), type.getIdentifier());
178     }
179
180     @Test
181     public void javaTypeForSchemaDefinitionForExtComplexUnionWithInnerUnionTypesTest() {
182         final var type = assertGeneratedMethod(
183             JavaTypeName.create(TEST_TYPE_PROVIDER, "UseOfUnions"), "getComplexUnion").getReturnType();
184         assertThat(type, instanceOf(GeneratedTransferObject.class));
185         assertEquals(JavaTypeName.create(TEST_TYPE_PROVIDER, "ComplexUnion"), type.getIdentifier());
186     }
187
188     @Test
189     public void javaTypeForSchemaDefinitionIdentityrefExtTypeTest() {
190         assertEquals(Types.parameterizedTypeFor(Types.CLASS,
191             Types.wildcardTypeFor(JavaTypeName.create(TEST_TYPE_PROVIDER, "CryptoAlg"))),
192             assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getCrypto").getReturnType());
193     }
194
195     @Test
196     public void javaTypeForSchemaDefinitionEmptyStringPatternTypeTest() {
197         final var restrictions = assertGTO(JavaTypeName.create(TEST_TYPE_PROVIDER, "EmptyPatternString"))
198             .getRestrictions();
199         final var patterns = restrictions.getPatternConstraints();
200         assertEquals(1, patterns.size());
201         final var pattern = patterns.get(0);
202         assertEquals("", pattern.getRegularExpressionString());
203         assertEquals("^(?:)$", pattern.getJavaPatternString());
204     }
205
206     @Test
207     public void testUnresolvedLeafref() {
208         assertSame(Types.objectType(),
209             assertGeneratedMethod(JavaTypeName.create(TEST_TYPE_PROVIDER_B, "Grp"), "getUnresolvableLeafref")
210                 .getReturnType());
211     }
212
213     @Test
214     public void javaTypeForSchemaDefinitionInvalidLeafrefPathTest() {
215         final var ctx = YangParserTestUtils.parseYangResource("/unresolvable-leafref.yang");
216         final var ex = assertThrows(IllegalArgumentException.class, () -> DefaultBindingGenerator.generateFor(ctx));
217         assertEquals("Failed to find leafref target /somewhere/i/belong", ex.getMessage());
218         final var cause = ex.getCause();
219         assertThat(cause, instanceOf(IllegalArgumentException.class));
220         assertEquals("Data tree child (foo)somewhere not present in module (foo)unresolvable-leafref",
221             cause.getMessage());
222     }
223
224     @Test
225     public void javaTypeForSchemaDefinitionConditionalLeafrefTest() {
226         // Note: previous incarnation did not resolve this, as the expression (pointed to a list)
227         assertSame(assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt16")),
228             assertGeneratedMethod(TEST_TYPE_PROVIDER_B_DATA, "getConditionalLeafref").getReturnType());
229     }
230
231     @Test
232     public void javaTypeForSchemaDefinitionLeafrefExtTypeTest() {
233         assertSame(assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8")),
234             assertGeneratedMethod(JavaTypeName.create(TEST_TYPE_PROVIDER, "Bar"), "getLeafrefValue").getReturnType());
235         assertSame(assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt16")),
236             assertGeneratedMethod(TEST_TYPE_PROVIDER_B_DATA, "getId").getReturnType());
237     }
238
239     @Test
240     public void javaTypeForSchemaDefinitionEnumExtTypeTest() {
241         final var expected = assertGeneratedType(JavaTypeName.create(BASE_YANG_TYPES, "YangEnumeration"));
242         assertThat(expected, instanceOf(Enumeration.class));
243         var enumValues = ((Enumeration) expected).getValues();
244         assertEquals(2, enumValues.size());
245         assertEquals("a", enumValues.get(0).getName());
246         assertEquals("A", enumValues.get(0).getMappedName());
247         assertEquals("b", enumValues.get(1).getName());
248         assertEquals("B", enumValues.get(1).getMappedName());
249
250         assertSame(expected, assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getResolveEnumLeaf").getReturnType());
251
252         // Note: this part of the test contained invalid assertion that the return would be java.lang.Enum
253         final var type = assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getResolveDirectUseOfEnum").getReturnType();
254         assertEquals(TEST_TYPE_PROVIDER_FOO.createEnclosed("ResolveDirectUseOfEnum"), type.getIdentifier());
255         assertThat(expected, instanceOf(Enumeration.class));
256         enumValues = ((Enumeration) type).getValues();
257         assertEquals(3, enumValues.size());
258         assertEquals("x", enumValues.get(0).getName());
259         assertEquals("X", enumValues.get(0).getMappedName());
260         assertEquals("y", enumValues.get(1).getName());
261         assertEquals("Y", enumValues.get(1).getMappedName());
262         assertEquals("z", enumValues.get(2).getName());
263         assertEquals("Z", enumValues.get(2).getMappedName());
264     }
265
266     @Test
267     public void javaTypeForSchemaDefinitionRestrictedExtTypeTest() {
268         final var expected = assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8Restricted"));
269         assertEquals(1, expected.getProperties().size());
270         final var rangeConstraints = expected.getRestrictions().getRangeConstraint();
271         assertTrue(rangeConstraints.isPresent());
272         final var it = rangeConstraints.orElseThrow().getAllowedRanges().asRanges().iterator();
273         assertTrue(it.hasNext());
274         final var constraint = it.next();
275         assertEquals((byte) 1, constraint.lowerEndpoint());
276         assertEquals((byte) 100, constraint.upperEndpoint());
277         assertFalse(it.hasNext());
278
279         assertSame(expected, assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getRestrictedInt8Type").getReturnType());
280     }
281
282     @Test
283     public void javaTypeForSchemaDefinitionExtTypeTest() {
284         final var expected = assertGTO(JavaTypeName.create(BASE_YANG_TYPES, "YangInt8"));
285         assertEquals(1, expected.getProperties().size());
286
287         assertSame(expected, assertGeneratedMethod(TEST_TYPE_PROVIDER_FOO, "getYangInt8Type").getReturnType());
288     }
289
290     private static MethodSignature assertGeneratedMethod(final JavaTypeName typeName, final String methodName) {
291         return assertGeneratedMethod(assertGeneratedType(typeName).getMethodDefinitions(), methodName);
292     }
293
294     private static MethodSignature assertGeneratedMethod(final List<MethodSignature> methods, final String name) {
295         return methods.stream().filter(method -> name.equals(method.getName()))
296             .findFirst()
297             .orElseThrow(() -> new AssertionError("Method " + name + " not present"));
298     }
299
300     private static GeneratedType assertGeneratedType(final JavaTypeName name) {
301         return TYPES.stream()
302             .filter(type -> name.equals(type.getIdentifier()))
303             .findFirst()
304             .orElseThrow(() -> new AssertionError("Generated type " + name + " not present"));
305     }
306
307     private static Enumeration assertEnumeration(final JavaTypeName name) {
308         final var type = assertGeneratedType(name);
309         assertThat(type, instanceOf(Enumeration.class));
310         return (Enumeration) type;
311     }
312
313     private static GeneratedTransferObject assertGTO(final JavaTypeName name) {
314         final var type = assertGeneratedType(name);
315         assertThat(type, instanceOf(GeneratedTransferObject.class));
316         return (GeneratedTransferObject) type;
317     }
318 }