2 * Copyright (c) 2016 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.mdsal.binding.java.api.generator;
10 import static org.junit.Assert.assertEquals;
11 import static org.mockito.Mockito.doReturn;
12 import static org.mockito.Mockito.mock;
13 import static org.mockito.Mockito.spy;
15 import java.util.ArrayList;
16 import java.util.List;
17 import java.util.stream.Collectors;
18 import org.junit.Test;
19 import org.opendaylight.mdsal.binding.generator.impl.DefaultBindingGenerator;
20 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
21 import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
22 import org.opendaylight.mdsal.binding.model.api.MethodSignature;
23 import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
24 import org.opendaylight.mdsal.binding.model.api.Type;
25 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
26 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
28 public class BuilderGeneratorTest {
29 private static final String TEST = "test";
30 private static final JavaTypeName TYPE_NAME = JavaTypeName.create(TEST, TEST);
33 public void basicTest() {
34 assertEquals("", new BuilderGenerator().generate(mock(Type.class)));
38 public void builderTemplateGenerateHashcodeWithPropertyTest() {
39 final GeneratedType genType = mockGenType("get" + TEST);
42 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
43 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
45 + " * results across all implementations.\n"
47 + " * @param obj Object for which to generate hashCode() result.\n"
48 + " * @return Hash code value of data modeled by this interface.\n"
49 + " * @throws NullPointerException if {@code obj} is null\n"
51 + "static int bindingHashCode(final test.test obj) {\n"
52 + " final int prime = 31;\n"
53 + " int result = 1;\n"
54 + " result = prime * result + Objects.hashCode(obj.getTest());\n"
56 + "}\n", genHashCode(genType).toString());
60 public void builderTemplateGenerateHashCodeWithoutAnyPropertyTest() throws Exception {
61 assertEquals("", genHashCode(mockGenType(TEST)).toString());
65 public void builderTemplateGenerateHashCodeWithMorePropertiesTest() throws Exception {
67 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
68 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
70 + " * results across all implementations.\n"
72 + " * @param obj Object for which to generate hashCode() result.\n"
73 + " * @return Hash code value of data modeled by this interface.\n"
74 + " * @throws NullPointerException if {@code obj} is null\n"
76 + "static int bindingHashCode(final test.test obj) {\n"
77 + " final int prime = 31;\n"
78 + " int result = 1;\n"
79 + " result = prime * result + Objects.hashCode(obj.getTest1());\n"
80 + " result = prime * result + Objects.hashCode(obj.getTest2());\n"
82 + "}\n", genHashCode(mockGenTypeMoreMeth("get" + TEST)).toString());
86 public void builderTemplateGenerateHashCodeWithoutPropertyWithAugmentTest() throws Exception {
88 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
89 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
91 + " * results across all implementations.\n"
93 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
95 + " * @param obj Object for which to generate hashCode() result.\n"
96 + " * @return Hash code value of data modeled by this interface.\n"
97 + " * @throws NullPointerException if {@code obj} is null\n"
99 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
101 + " final int prime = 31;\n"
102 + " int result = 1;\n"
103 + " result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
104 + " return result;\n"
105 + "}\n", genHashCode(mockAugment(mockGenType(TEST))).toString());
109 public void builderTemplateGenerateHashCodeWithPropertyWithAugmentTest() throws Exception {
111 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
112 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
114 + " * results across all implementations.\n"
116 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
118 + " * @param obj Object for which to generate hashCode() result.\n"
119 + " * @return Hash code value of data modeled by this interface.\n"
120 + " * @throws NullPointerException if {@code obj} is null\n"
122 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
124 + " final int prime = 31;\n"
125 + " int result = 1;\n"
126 + " result = prime * result + Objects.hashCode(obj.getTest());\n"
127 + " result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
128 + " return result;\n"
129 + "}\n", genHashCode(mockAugment(mockGenType("get" + TEST))).toString());
133 public void builderTemplateGenerateHashCodeWithMorePropertiesWithAugmentTest() throws Exception {
135 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
136 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
138 + " * results across all implementations.\n"
140 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
142 + " * @param obj Object for which to generate hashCode() result.\n"
143 + " * @return Hash code value of data modeled by this interface.\n"
144 + " * @throws NullPointerException if {@code obj} is null\n"
146 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
148 + " final int prime = 31;\n"
149 + " int result = 1;\n"
150 + " result = prime * result + Objects.hashCode(obj.getTest1());\n"
151 + " result = prime * result + Objects.hashCode(obj.getTest2());\n"
152 + " result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
153 + " return result;\n"
154 + "}\n", genHashCode(mockAugment(mockGenTypeMoreMeth("get" + TEST))).toString());
158 public void builderTemplateGenerateToStringWithPropertyTest() {
159 final GeneratedType genType = mockGenType("get" + TEST);
162 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
163 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
164 + "\n * representations across all implementations.\n"
166 + " * @param obj Object for which to generate toString() result.\n"
167 + " * @return {@link String} value of data modeled by this interface.\n"
168 + " * @throws NullPointerException if {@code obj} is null\n"
170 + "static String bindingToString(final test.test obj) {\n"
171 + " final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
172 + " CodeHelpers.appendValue(helper, \"test\", obj.gettest());\n"
173 + " return helper.toString();\n"
174 + "}\n", genToString(genType).toString());
178 public void builderTemplateGenerateToStringWithoutAnyPropertyTest() throws Exception {
180 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
181 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
182 + "\n * representations across all implementations.\n"
184 + " * @param obj Object for which to generate toString() result.\n"
185 + " * @return {@link String} value of data modeled by this interface.\n"
186 + " * @throws NullPointerException if {@code obj} is null\n"
188 + "static String bindingToString(final test.test obj) {\n"
189 + " final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
190 + " return helper.toString();\n"
191 + "}\n", genToString(mockGenType(TEST)).toString());
195 public void builderTemplateGenerateToStringWithMorePropertiesTest() throws Exception {
197 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
198 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
199 + "\n * representations across all implementations.\n"
201 + " * @param obj Object for which to generate toString() result.\n"
202 + " * @return {@link String} value of data modeled by this interface.\n"
203 + " * @throws NullPointerException if {@code obj} is null\n"
205 + "static String bindingToString(final test.test obj) {\n"
206 + " final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
207 + " CodeHelpers.appendValue(helper, \"test1\", obj.gettest1());\n"
208 + " CodeHelpers.appendValue(helper, \"test2\", obj.gettest2());\n"
209 + " return helper.toString();\n"
210 + "}\n", genToString(mockGenTypeMoreMeth("get" + TEST)).toString());
214 public void builderTemplateGenerateToStringWithoutPropertyWithAugmentTest() throws Exception {
216 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
217 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
218 + "\n * representations across all implementations.\n"
220 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
222 + " * @param obj Object for which to generate toString() result.\n"
223 + " * @return {@link String} value of data modeled by this interface.\n"
224 + " * @throws NullPointerException if {@code obj} is null\n"
226 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
228 + " final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
229 + " CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
230 + " return helper.toString();\n"
231 + "}\n", genToString(mockAugment(mockGenType(TEST))).toString());
235 public void builderTemplateGenerateToStringWithPropertyWithAugmentTest() throws Exception {
237 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
238 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
239 + "\n * representations across all implementations.\n"
241 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
243 + " * @param obj Object for which to generate toString() result.\n"
244 + " * @return {@link String} value of data modeled by this interface.\n"
245 + " * @throws NullPointerException if {@code obj} is null\n"
247 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
249 + " final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
250 + " CodeHelpers.appendValue(helper, \"test\", obj.gettest());\n"
251 + " CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
252 + " return helper.toString();\n"
253 + "}\n", genToString(mockAugment(mockGenType("get" + TEST))).toString());
257 public void builderTemplateGenerateToStringWithMorePropertiesWithAugmentTest() throws Exception {
259 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
260 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
261 + "\n * representations across all implementations.\n"
263 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
265 + " * @param obj Object for which to generate toString() result.\n"
266 + " * @return {@link String} value of data modeled by this interface.\n"
267 + " * @throws NullPointerException if {@code obj} is null\n"
269 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
271 + " final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
272 + " CodeHelpers.appendValue(helper, \"test1\", obj.gettest1());\n"
273 + " CodeHelpers.appendValue(helper, \"test2\", obj.gettest2());\n"
274 + " CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
275 + " return helper.toString();\n"
276 + "}\n", genToString(mockAugment(mockGenTypeMoreMeth("get" + TEST))).toString());
280 public void builderTemplateGenerateToEqualsComparingOrderTest() {
281 final EffectiveModelContext context = YangParserTestUtils.parseYangResource(
283 final List<Type> types = new DefaultBindingGenerator().generateTypes(context);
284 final BuilderTemplate bt = BuilderGenerator.templateForType((GeneratedType) types.get(19));
286 final List<String> sortedProperties = bt.properties.stream()
287 .sorted(ByTypeMemberComparator.getInstance())
288 .map(BuilderGeneratedProperty::getName)
289 .collect(Collectors.toList());
291 assertEquals(List.of(
292 // numeric types (boolean, byte, short, int, long, biginteger, bigdecimal), identityrefs, empty
293 "id16", "id16Def", "id32", "id32Def", "id64", "id64Def", "id8", "id8Def", "idBoolean", "idBooleanDef",
294 "idDecimal64", "idDecimal64Def","idEmpty", "idEmptyDef", "idIdentityref", "idIdentityrefDef",
295 "idLeafref", "idLeafrefDef", "idU16", "idU16Def", "idU32", "idU32Def", "idU64", "idU64Def", "idU8",
297 // string, binary, bits
298 "idBinary", "idBinaryDef", "idBits", "idBitsDef", "idGroupLeafString", "idLeafrefContainer1",
299 "idLeafrefContainer1Def", "idString", "idStringDef",
300 // instance identifier
301 "idInstanceIdentifier", "idInstanceIdentifierDef",
303 "idContainer1", "idContainer2", "idEnumeration", "idEnumerationDef",
304 "idGroupContainer", "idList", "idUnion", "idUnionDef"), sortedProperties);
307 private static GeneratedType mockAugment(final GeneratedType genType) {
308 final List<Type> impls = new ArrayList<>();
309 final Type impl = mock(Type.class);
310 doReturn("org.opendaylight.yangtools.yang.binding.Augmentable").when(impl).getFullyQualifiedName();
312 doReturn(impls).when(genType).getImplements();
316 private static GeneratedType mockGenTypeMoreMeth(final String methodeName) {
317 final GeneratedType genType = spy(GeneratedType.class);
318 doReturn(TYPE_NAME).when(genType).getIdentifier();
319 doReturn(TEST).when(genType).getName();
320 doReturn(TEST).when(genType).getPackageName();
322 final List<MethodSignature> listMethodSign = new ArrayList<>();
323 for (int i = 0; i < 2; i++) {
324 final MethodSignature methSign = mockMethSign(methodeName + (i + 1));
325 listMethodSign.add(methSign);
327 doReturn(listMethodSign).when(genType).getMethodDefinitions();
329 final List<Type> impls = new ArrayList<>();
330 doReturn(impls).when(genType).getImplements();
334 private static CharSequence genToString(final GeneratedType genType) {
335 return new InterfaceTemplate(genType).generateBindingToString();
338 private static CharSequence genHashCode(final GeneratedType genType) {
339 return new InterfaceTemplate(genType).generateBindingHashCode();
342 private static GeneratedType mockGenType(final String methodeName) {
343 final GeneratedType genType = spy(GeneratedType.class);
344 doReturn(TYPE_NAME).when(genType).getIdentifier();
345 doReturn(TEST).when(genType).getName();
346 doReturn(TEST).when(genType).getPackageName();
348 final List<MethodSignature> listMethodSign = new ArrayList<>();
349 final MethodSignature methSign = mockMethSign(methodeName);
350 listMethodSign.add(methSign);
351 doReturn(listMethodSign).when(genType).getMethodDefinitions();
353 final List<Type> impls = new ArrayList<>();
354 doReturn(impls).when(genType).getImplements();
358 private static MethodSignature mockMethSign(final String methodeName) {
359 final MethodSignature methSign = mock(MethodSignature.class);
360 doReturn(methodeName).when(methSign).getName();
361 final Type methType = mock(Type.class);
362 doReturn(TYPE_NAME).when(methType).getIdentifier();
363 doReturn(TEST).when(methType).getName();
364 doReturn(methType).when(methSign).getReturnType();
365 doReturn(ValueMechanics.NORMAL).when(methSign).getMechanics();