Bump versions to 14.0.0-SNAPSHOT
[mdsal.git] / binding / mdsal-binding-generator / src / test / java / org / opendaylight / mdsal / binding / generator / impl / Mdsal675Test.java
1 /*
2  * Copyright (c) 2022 PANTHEON.tech s.r.o. 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 package org.opendaylight.mdsal.binding.generator.impl;
9
10 import static org.hamcrest.MatcherAssert.assertThat;
11 import static org.hamcrest.Matchers.in;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertNotNull;
14 import static org.junit.Assert.assertTrue;
15
16 import com.google.common.collect.ImmutableMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.stream.Collectors;
21 import org.junit.Test;
22 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
23 import org.opendaylight.mdsal.binding.model.api.MethodSignature;
24 import org.opendaylight.mdsal.binding.model.api.Type;
25 import org.opendaylight.mdsal.binding.model.ri.BaseYangTypes;
26 import org.opendaylight.mdsal.binding.model.ri.BindingTypes;
27 import org.opendaylight.mdsal.binding.model.ri.Types;
28 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
29
30 public class Mdsal675Test {
31     private static final String PACKAGE = "org.opendaylight.yang.gen.v1.urn.test.yang.data.demo.norev.";
32     private static final String PACKAGE2 = "org.opendaylight.yang.gen.v1.urn.test.yang.data.naming.norev.";
33     private static final String MODULE_CLASS_NAME = PACKAGE + "YangDataDemoData";
34     private static final String ROOT_CONTAINER_CLASS_NAME = PACKAGE + "RootContainer";
35     private static final Map<String, Type> INTERFACE_METHODS =
36             Map.of("implementedInterface", Types.typeForClass(Class.class));
37
38     @Test
39     public void yangDataGen() {
40         final List<GeneratedType> allGenTypes = DefaultBindingGenerator.generateFor(
41                 YangParserTestUtils.parseYangResources(Mdsal675Test.class,
42                         "/yang-data-models/ietf-restconf.yang", "/yang-data-models/yang-data-demo.yang"));
43         assertNotNull(allGenTypes);
44         assertEquals(29, allGenTypes.size());
45         final Map<String, GeneratedType> genTypesMap = allGenTypes.stream()
46                 .collect(ImmutableMap.toImmutableMap(type -> type.getIdentifier().toString(), type -> type));
47
48         // ensure generated yang-data classes contain getters for inner structure types
49
50         // yang-data > container
51         assertYangDataGenType(
52                 assertGenType(genTypesMap, PACKAGE + "YangDataWithContainer"),
53                 assertGenType(genTypesMap, PACKAGE + "yang.data.with.container.ContainerFromYangData"),
54                 List.of("getContainerFromYangData", "nonnullContainerFromYangData"));
55         // yang-data > list
56         assertYangDataGenType(
57                 assertGenType(genTypesMap, PACKAGE + "YangDataWithList"),
58                 Types.listTypeFor(assertGenType(genTypesMap, PACKAGE + "yang.data.with.list.ListFromYangData")),
59                 List.of("getListFromYangData", "nonnullListFromYangData"));
60         // yang-data > leaf
61         assertYangDataGenType(
62                 assertGenType(genTypesMap, PACKAGE + "YangDataWithLeaf"),
63                 BaseYangTypes.STRING_TYPE,
64                 List.of("getLeafFromYangData", "requireLeafFromYangData"));
65         // yang-data > leaf-list
66         assertYangDataGenType(
67                 assertGenType(genTypesMap, PACKAGE + "YangDataWithLeafList"),
68                 Types.setTypeFor(BaseYangTypes.STRING_TYPE),
69                 List.of("getLeafListFromYangData", "requireLeafListFromYangData"));
70         // yang-data > anydata
71         assertYangDataGenType(
72                 assertGenType(genTypesMap, PACKAGE + "YangDataWithAnydata"),
73                 assertGenType(genTypesMap, PACKAGE + "yang.data.with.anydata.AnydataFromYangData"),
74                 List.of("getAnydataFromYangData", "requireAnydataFromYangData"));
75         // yang-data > anyxml
76         assertYangDataGenType(
77                 assertGenType(genTypesMap, PACKAGE + "YangDataWithAnyxml"),
78                 assertGenType(genTypesMap, PACKAGE + "yang.data.with.anyxml.AnyxmlFromYangData"),
79                 List.of("getAnyxmlFromYangData", "requireAnyxmlFromYangData"));
80
81         // ensure generated yang-data classes extending inner group so group content is reachable
82
83         // yang-data > uses > group > container
84         assertYangDataGenType(
85                 assertGenType(genTypesMap, PACKAGE + "YangDataWithContainerFromGroup"),
86                 assertGenType(genTypesMap, PACKAGE + "GrpForContainer"),
87                 assertGenType(genTypesMap, PACKAGE + "grp._for.container.ContainerFromGroup"),
88                 List.of("getContainerFromGroup", "nonnullContainerFromGroup"));
89         // yang-data > uses > group > list
90         assertYangDataGenType(
91                 assertGenType(genTypesMap, PACKAGE + "YangDataWithListFromGroup"),
92                 assertGenType(genTypesMap, PACKAGE + "GrpForList"),
93                 Types.listTypeFor(assertGenType(genTypesMap, PACKAGE + "grp._for.list.ListFromGroup")),
94                 List.of("getListFromGroup", "nonnullListFromGroup")
95         );
96         // yang-data > uses > group > leaf
97         assertYangDataGenType(
98                 assertGenType(genTypesMap, PACKAGE + "YangDataWithLeafFromGroup"),
99                 assertGenType(genTypesMap, PACKAGE + "GrpForLeaf"),
100                 BaseYangTypes.UINT32_TYPE,
101                 List.of("getLeafFromGroup", "requireLeafFromGroup"));
102         // yang-data > uses > group > leaf-list
103         assertYangDataGenType(
104                 assertGenType(genTypesMap, PACKAGE + "YangDataWithLeafListFromGroup"),
105                 assertGenType(genTypesMap, PACKAGE + "GrpForLeafList"),
106                 Types.setTypeFor(BaseYangTypes.UINT32_TYPE),
107                 List.of("getLeafListFromGroup", "requireLeafListFromGroup"));
108         // yang-data > uses > group > anydata
109         assertYangDataGenType(
110                 assertGenType(genTypesMap, PACKAGE + "YangDataWithAnydataFromGroup"),
111                 assertGenType(genTypesMap, PACKAGE + "GrpForAnydata"),
112                 assertGenType(genTypesMap, PACKAGE + "grp._for.anydata.AnydataFromGroup"),
113                 List.of("getAnydataFromGroup", "requireAnydataFromGroup"));
114         // yang-data > uses > group > anyxml
115         assertYangDataGenType(
116                 assertGenType(genTypesMap, PACKAGE + "YangDataWithAnyxmlFromGroup"),
117                 assertGenType(genTypesMap, PACKAGE + "GrpForAnyxml"),
118                 assertGenType(genTypesMap, PACKAGE + "grp._for.anyxml.AnyxmlFromGroup"),
119                 List.of("getAnyxmlFromGroup", "requireAnyxmlFromGroup"));
120
121         // ensure module class has only getter for root container
122         final GeneratedType moduleType = assertGenType(genTypesMap, MODULE_CLASS_NAME);
123         assertNotNull(moduleType.getMethodDefinitions());
124         assertEquals(List.of("getRootContainer"),
125                 moduleType.getMethodDefinitions().stream().map(MethodSignature::getName)
126                         .filter(methodName -> methodName.startsWith("get")).toList());
127
128         // ensure yang-data at non-top level is ignored (no getters in parent container)
129         GeneratedType rootContainerType = assertGenType(genTypesMap, ROOT_CONTAINER_CLASS_NAME);
130         assertNotNull(rootContainerType.getMethodDefinitions());
131         assertTrue(rootContainerType.getMethodDefinitions().stream()
132                 .filter(method -> method.getName().startsWith("get"))
133                 .findFirst().isEmpty());
134     }
135
136     @Test
137     public void yangDataNamingStrategy() {
138         final List<GeneratedType> allGenTypes = DefaultBindingGenerator.generateFor(
139                 YangParserTestUtils.parseYangResources(Mdsal675Test.class,
140                         "/yang-data-models/ietf-restconf.yang", "/yang-data-models/yang-data-naming.yang"));
141         assertNotNull(allGenTypes);
142         assertEquals(22, allGenTypes.size());
143         final Set<String> genTypeNames =
144                 allGenTypes.stream().map(type -> type.getIdentifier().toString()).collect(Collectors.toSet());
145
146         // template name is not compliant to YANG identifier -> char encoding used, name starts with $ char
147         // a) latin1, but not a valid Java identifier
148         assertTrue(genTypeNames.contains(PACKAGE2 + "$ľaľa$20$ho$2C$$20$papľuha$2C$$20$ogrcal$20$mi$20$krpce$21$"));
149         // b) cyrillic, but a valid Java identifier
150         assertTrue(genTypeNames.contains(PACKAGE2 + "привет"));
151
152         // template name is compliant to yang identifier -> camel-case used
153         assertTrue(genTypeNames.contains(PACKAGE2 + "IdentifierCompliantName"));
154
155         // name collision with a typedef
156         assertTrue(genTypeNames.contains(PACKAGE2 + "Collision1$T"));
157         assertTrue(genTypeNames.contains(PACKAGE2 + "collision1.Collision1"));
158         assertTrue(genTypeNames.contains(PACKAGE2 + "Collision1$YD"));
159
160         // name collision with top level container
161         assertTrue(genTypeNames.contains(PACKAGE2 + "Collision2"));
162         assertTrue(genTypeNames.contains(PACKAGE2 + "Collision2$YD"));
163
164         // name collision with group used
165         assertTrue(genTypeNames.contains(PACKAGE2 + "Collision3$G"));
166         assertTrue(genTypeNames.contains(PACKAGE2 + "Collision3$YD"));
167
168         // rc:yang-data .-/#
169         assertTrue(genTypeNames.contains(PACKAGE2 + "$$2E$$2D$$2F$$23$"));
170         assertTrue(genTypeNames.contains(PACKAGE2 + "$$2e$$2d$$2f$$23$$.Foo"));
171
172         // rc:yang-data -./#
173         assertTrue(genTypeNames.contains(PACKAGE2 + "$$2D$$2E$$2F$$23$"));
174         assertTrue(genTypeNames.contains(PACKAGE2 + "$$2d$$2e$$2f$$23$$.Foo"));
175     }
176
177     private static GeneratedType assertGenType(final Map<String, GeneratedType> genTypesMap, final String className) {
178         final var ret = genTypesMap.get(className);
179         assertNotNull("no type generated: " + className, ret);
180         return ret;
181     }
182
183     private static void assertYangDataGenType(final GeneratedType yangDataType, final Type contentType,
184             final List<String> getterMethods) {
185         assertImplements(yangDataType, BindingTypes.yangData(yangDataType));
186         INTERFACE_METHODS.forEach((name, type) -> assertHasMethod(yangDataType, name, type));
187         for (final String methodName : getterMethods) {
188             assertHasMethod(yangDataType, methodName, contentType);
189         }
190     }
191
192     private static void assertYangDataGenType(final GeneratedType yangDataType, final GeneratedType groupType,
193             final Type contentType, final List<String> getterMethods) {
194         assertImplements(yangDataType, BindingTypes.yangData(yangDataType));
195         assertImplements(yangDataType, groupType);
196         INTERFACE_METHODS.forEach((name, type) -> assertHasMethod(yangDataType, name, type));
197         for (final String methodName : getterMethods) {
198             assertHasMethod(groupType, methodName, contentType);
199         }
200     }
201
202     private static void assertHasMethod(final GeneratedType genType, final String methodName,
203             final Type returnType) {
204         assertTrue("no expected method " + methodName + " returning " + returnType,
205             genType.getMethodDefinitions().stream().anyMatch(
206                 method -> methodName.equals(method.getName()) && returnType.equals(method.getReturnType())));
207     }
208
209     private static void assertImplements(final GeneratedType genType, final Type implementedType) {
210         assertThat(implementedType, in(genType.getImplements()));
211     }
212
213 }