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