08c0482d83750b2dc18f7449dae34dda48b3a7c4
[mdsal.git] / binding / mdsal-binding-java-api-generator / src / test / java / org / opendaylight / mdsal / binding / java / api / generator / BuilderGeneratorTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  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.java.api.generator;
9
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;
14
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;
27
28 public class BuilderGeneratorTest {
29     private static final String TEST = "test";
30     private static final JavaTypeName TYPE_NAME = JavaTypeName.create(TEST, TEST);
31
32     @Test
33     public void basicTest() {
34         assertEquals("", new BuilderGenerator().generate(mock(Type.class)));
35     }
36
37     @Test
38     public void builderTemplateGenerateHashcodeWithPropertyTest() {
39         final GeneratedType genType = mockGenType("get" + TEST);
40
41         assertEquals("/**\n"
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"
44                 + " hashing\n"
45                 + " * results across all implementations.\n"
46                 + " *\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"
50                 + " */\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"
55                 + "    return result;\n"
56                 + "}\n", genHashCode(genType).toString());
57     }
58
59     @Test
60     public void builderTemplateGenerateHashCodeWithMorePropertiesTest() throws Exception {
61         assertEquals("/**\n"
62                 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
63                 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
64                 + " hashing\n"
65                 + " * results across all implementations.\n"
66                 + " *\n"
67                 + " * @param obj Object for which to generate hashCode() result.\n"
68                 + " * @return Hash code value of data modeled by this interface.\n"
69                 + " * @throws NullPointerException if {@code obj} is null\n"
70                 + " */\n"
71                 + "static int bindingHashCode(final test.test obj) {\n"
72                 + "    final int prime = 31;\n"
73                 + "    int result = 1;\n"
74                 + "    result = prime * result + Objects.hashCode(obj.getTest1());\n"
75                 + "    result = prime * result + Objects.hashCode(obj.getTest2());\n"
76                 + "    return result;\n"
77                 + "}\n", genHashCode(mockGenTypeMoreMeth("get" + TEST)).toString());
78     }
79
80     @Test
81     public void builderTemplateGenerateHashCodeWithoutPropertyWithAugmentTest() throws Exception {
82         assertEquals("/**\n"
83                 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
84                 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
85                 + " hashing\n"
86                 + " * results across all implementations.\n"
87                 + " *\n"
88                 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
89                 + " *              contract.\n"
90                 + " * @param obj Object for which to generate hashCode() result.\n"
91                 + " * @return Hash code value of data modeled by this interface.\n"
92                 + " * @throws NullPointerException if {@code obj} is null\n"
93                 + " */\n"
94                 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
95                 + "\n"
96                 + "    final int prime = 31;\n"
97                 + "    int result = 1;\n"
98                 + "    result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
99                 + "    return result;\n"
100                 + "}\n", genHashCode(mockAugment(mockGenType(TEST))).toString());
101     }
102
103     @Test
104     public void builderTemplateGenerateHashCodeWithPropertyWithAugmentTest() throws Exception {
105         assertEquals("/**\n"
106                 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
107                 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
108                 + " hashing\n"
109                 + " * results across all implementations.\n"
110                 + " *\n"
111                 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
112                 + " *              contract.\n"
113                 + " * @param obj Object for which to generate hashCode() result.\n"
114                 + " * @return Hash code value of data modeled by this interface.\n"
115                 + " * @throws NullPointerException if {@code obj} is null\n"
116                 + " */\n"
117                 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
118                 + "\n"
119                 + "    final int prime = 31;\n"
120                 + "    int result = 1;\n"
121                 + "    result = prime * result + Objects.hashCode(obj.getTest());\n"
122                 + "    result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
123                 + "    return result;\n"
124                 + "}\n", genHashCode(mockAugment(mockGenType("get" + TEST))).toString());
125     }
126
127     @Test
128     public void builderTemplateGenerateHashCodeWithMorePropertiesWithAugmentTest() throws Exception {
129         assertEquals("/**\n"
130                 + " * Default implementation of {@link Object#hashCode()} contract for this interface.\n"
131                 + " * Implementations of this interface are encouraged to defer to this method to get consistent"
132                 + " hashing\n"
133                 + " * results across all implementations.\n"
134                 + " *\n"
135                 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
136                 + " *              contract.\n"
137                 + " * @param obj Object for which to generate hashCode() result.\n"
138                 + " * @return Hash code value of data modeled by this interface.\n"
139                 + " * @throws NullPointerException if {@code obj} is null\n"
140                 + " */\n"
141                 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
142                 + "\n"
143                 + "    final int prime = 31;\n"
144                 + "    int result = 1;\n"
145                 + "    result = prime * result + Objects.hashCode(obj.getTest1());\n"
146                 + "    result = prime * result + Objects.hashCode(obj.getTest2());\n"
147                 + "    result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
148                 + "    return result;\n"
149                 + "}\n", genHashCode(mockAugment(mockGenTypeMoreMeth("get" + TEST))).toString());
150     }
151
152     @Test
153     public void builderTemplateGenerateToStringWithPropertyTest() {
154         final GeneratedType genType = mockGenType("get" + TEST);
155
156         assertEquals("/**\n"
157                 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
158                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
159                 + "\n * representations across all implementations.\n"
160                 + " *\n"
161                 + " * @param obj Object for which to generate toString() result.\n"
162                 + " * @return {@link String} value of data modeled by this interface.\n"
163                 + " * @throws NullPointerException if {@code obj} is null\n"
164                 + " */\n"
165                 + "static String bindingToString(final test.test obj) {\n"
166                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
167                 + "    CodeHelpers.appendValue(helper, \"test\", obj.gettest());\n"
168                 + "    return helper.toString();\n"
169                 + "}\n", genToString(genType).toString());
170     }
171
172     @Test
173     public void builderTemplateGenerateToStringWithoutAnyPropertyTest() throws Exception {
174         assertEquals("/**\n"
175                 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
176                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
177                 + "\n * representations across all implementations.\n"
178                 + " *\n"
179                 + " * @param obj Object for which to generate toString() result.\n"
180                 + " * @return {@link String} value of data modeled by this interface.\n"
181                 + " * @throws NullPointerException if {@code obj} is null\n"
182                 + " */\n"
183                 + "static String bindingToString(final test.test obj) {\n"
184                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
185                 + "    return helper.toString();\n"
186                 + "}\n", genToString(mockGenType(TEST)).toString());
187     }
188
189     @Test
190     public void builderTemplateGenerateToStringWithMorePropertiesTest() throws Exception {
191         assertEquals("/**\n"
192                 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
193                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
194                 + "\n * representations across all implementations.\n"
195                 + " *\n"
196                 + " * @param obj Object for which to generate toString() result.\n"
197                 + " * @return {@link String} value of data modeled by this interface.\n"
198                 + " * @throws NullPointerException if {@code obj} is null\n"
199                 + " */\n"
200                 + "static String bindingToString(final test.test obj) {\n"
201                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
202                 + "    CodeHelpers.appendValue(helper, \"test1\", obj.gettest1());\n"
203                 + "    CodeHelpers.appendValue(helper, \"test2\", obj.gettest2());\n"
204                 + "    return helper.toString();\n"
205                 + "}\n", genToString(mockGenTypeMoreMeth("get" + TEST)).toString());
206     }
207
208     @Test
209     public void builderTemplateGenerateToStringWithoutPropertyWithAugmentTest() throws Exception {
210         assertEquals("/**\n"
211                 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
212                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
213                 + "\n * representations across all implementations.\n"
214                 + " *\n"
215                 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
216                 + " *              contract.\n"
217                 + " * @param obj Object for which to generate toString() result.\n"
218                 + " * @return {@link String} value of data modeled by this interface.\n"
219                 + " * @throws NullPointerException if {@code obj} is null\n"
220                 + " */\n"
221                 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
222                 + " T$$ obj) {\n"
223                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
224                 + "    CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
225                 + "    return helper.toString();\n"
226                 + "}\n", genToString(mockAugment(mockGenType(TEST))).toString());
227     }
228
229     @Test
230     public void builderTemplateGenerateToStringWithPropertyWithAugmentTest() throws Exception {
231         assertEquals("/**\n"
232                 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
233                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
234                 + "\n * representations across all implementations.\n"
235                 + " *\n"
236                 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
237                 + " *              contract.\n"
238                 + " * @param obj Object for which to generate toString() result.\n"
239                 + " * @return {@link String} value of data modeled by this interface.\n"
240                 + " * @throws NullPointerException if {@code obj} is null\n"
241                 + " */\n"
242                 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
243                 + " T$$ obj) {\n"
244                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
245                 + "    CodeHelpers.appendValue(helper, \"test\", obj.gettest());\n"
246                 + "    CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
247                 + "    return helper.toString();\n"
248                 + "}\n", genToString(mockAugment(mockGenType("get" + TEST))).toString());
249     }
250
251     @Test
252     public void builderTemplateGenerateToStringWithMorePropertiesWithAugmentTest() throws Exception {
253         assertEquals("/**\n"
254                 + " * Default implementation of {@link Object#toString()} contract for this interface.\n"
255                 + " * Implementations of this interface are encouraged to defer to this method to get consistent string"
256                 + "\n * representations across all implementations.\n"
257                 + " *\n"
258                 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\n"
259                 + " *              contract.\n"
260                 + " * @param obj Object for which to generate toString() result.\n"
261                 + " * @return {@link String} value of data modeled by this interface.\n"
262                 + " * @throws NullPointerException if {@code obj} is null\n"
263                 + " */\n"
264                 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
265                 + " T$$ obj) {\n"
266                 + "    final MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(\"test\");\n"
267                 + "    CodeHelpers.appendValue(helper, \"test1\", obj.gettest1());\n"
268                 + "    CodeHelpers.appendValue(helper, \"test2\", obj.gettest2());\n"
269                 + "    CodeHelpers.appendValue(helper, \"augmentation\", obj.augmentations().values());\n"
270                 + "    return helper.toString();\n"
271                 + "}\n", genToString(mockAugment(mockGenTypeMoreMeth("get" + TEST))).toString());
272     }
273
274     @Test
275     public void builderTemplateGenerateToEqualsComparingOrderTest() {
276         final EffectiveModelContext context = YangParserTestUtils.parseYangResource(
277                 "/test-types.yang");
278         final List<Type> types = new DefaultBindingGenerator().generateTypes(context);
279         final BuilderTemplate bt = BuilderGenerator.templateForType((GeneratedType) types.get(19));
280
281         final List<String> sortedProperties = bt.properties.stream()
282                 .sorted(ByTypeMemberComparator.getInstance())
283                 .map(BuilderGeneratedProperty::getName)
284                 .collect(Collectors.toList());
285
286         assertEquals(List.of(
287                 // numeric types (boolean, byte, short, int, long, biginteger, bigdecimal), identityrefs, empty
288                 "id16", "id16Def", "id32", "id32Def", "id64", "id64Def", "id8", "id8Def", "idBoolean", "idBooleanDef",
289                 "idDecimal64", "idDecimal64Def","idEmpty", "idEmptyDef", "idIdentityref", "idIdentityrefDef",
290                 "idLeafref", "idLeafrefDef", "idU16", "idU16Def", "idU32", "idU32Def", "idU64", "idU64Def", "idU8",
291                 "idU8Def",
292                 // string, binary, bits
293                 "idBinary", "idBinaryDef", "idBits", "idBitsDef", "idGroupLeafString", "idLeafrefContainer1",
294                 "idLeafrefContainer1Def", "idString", "idStringDef",
295                 // instance identifier
296                 "idInstanceIdentifier", "idInstanceIdentifierDef",
297                 // other types
298                 "idContainer1", "idContainer2", "idEnumeration", "idEnumerationDef",
299                 "idGroupContainer", "idList", "idUnion", "idUnionDef"), sortedProperties);
300     }
301
302     private static GeneratedType mockAugment(final GeneratedType genType) {
303         final List<Type> impls = new ArrayList<>();
304         final Type impl = mock(Type.class);
305         doReturn("org.opendaylight.yangtools.yang.binding.Augmentable").when(impl).getFullyQualifiedName();
306         impls.add(impl);
307         doReturn(impls).when(genType).getImplements();
308         return genType;
309     }
310
311     private static GeneratedType mockGenTypeMoreMeth(final String methodeName) {
312         final GeneratedType genType = spy(GeneratedType.class);
313         doReturn(TYPE_NAME).when(genType).getIdentifier();
314         doReturn(TEST).when(genType).getName();
315         doReturn(TEST).when(genType).getPackageName();
316
317         final List<MethodSignature> listMethodSign = new ArrayList<>();
318         for (int i = 0; i < 2; i++) {
319             final MethodSignature methSign = mockMethSign(methodeName + (i + 1));
320             listMethodSign.add(methSign);
321         }
322         doReturn(listMethodSign).when(genType).getMethodDefinitions();
323
324         final List<Type> impls = new ArrayList<>();
325         doReturn(impls).when(genType).getImplements();
326         return genType;
327     }
328
329     private static CharSequence genToString(final GeneratedType genType) {
330         return new InterfaceTemplate(genType).generateBindingToString();
331     }
332
333     private static CharSequence genHashCode(final GeneratedType genType) {
334         return new InterfaceTemplate(genType).generateBindingHashCode();
335     }
336
337     private static GeneratedType mockGenType(final String methodeName) {
338         final GeneratedType genType = spy(GeneratedType.class);
339         doReturn(TYPE_NAME).when(genType).getIdentifier();
340         doReturn(TEST).when(genType).getName();
341         doReturn(TEST).when(genType).getPackageName();
342
343         final List<MethodSignature> listMethodSign = new ArrayList<>();
344         final MethodSignature methSign = mockMethSign(methodeName);
345         listMethodSign.add(methSign);
346         doReturn(listMethodSign).when(genType).getMethodDefinitions();
347
348         final List<Type> impls = new ArrayList<>();
349         doReturn(impls).when(genType).getImplements();
350         return genType;
351     }
352
353     private static MethodSignature mockMethSign(final String methodeName) {
354         final MethodSignature methSign = mock(MethodSignature.class);
355         doReturn(methodeName).when(methSign).getName();
356         final Type methType = mock(Type.class);
357         doReturn(TYPE_NAME).when(methType).getIdentifier();
358         doReturn(TEST).when(methType).getName();
359         doReturn(methType).when(methSign).getReturnType();
360         doReturn(ValueMechanics.NORMAL).when(methSign).getMechanics();
361         return methSign;
362     }
363 }