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 builderTemplateGenerateHashCodeWithMorePropertiesTest() throws Exception {
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"
65 + " * results across all implementations.\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"
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"
77 + "}\n", genHashCode(mockGenTypeMoreMeth("get" + TEST)).toString());
81 public void builderTemplateGenerateHashCodeWithoutPropertyWithAugmentTest() throws Exception {
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"
86 + " * results across all implementations.\n"
88 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\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"
94 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
96 + " final int prime = 31;\n"
97 + " int result = 1;\n"
98 + " result = prime * result + CodeHelpers.hashAugmentations(obj);\n"
100 + "}\n", genHashCode(mockAugment(mockGenType(TEST))).toString());
104 public void builderTemplateGenerateHashCodeWithPropertyWithAugmentTest() throws Exception {
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"
109 + " * results across all implementations.\n"
111 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\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"
117 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
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());
128 public void builderTemplateGenerateHashCodeWithMorePropertiesWithAugmentTest() throws Exception {
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"
133 + " * results across all implementations.\n"
135 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\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"
141 + "static <T$$ extends test.test & AugmentationHolder<?>> int bindingHashCode(final @NonNull T$$ obj) {"
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());
153 public void builderTemplateGenerateToStringWithPropertyTest() {
154 final GeneratedType genType = mockGenType("get" + TEST);
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"
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"
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());
173 public void builderTemplateGenerateToStringWithoutAnyPropertyTest() throws Exception {
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"
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"
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());
190 public void builderTemplateGenerateToStringWithMorePropertiesTest() throws Exception {
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"
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"
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());
209 public void builderTemplateGenerateToStringWithoutPropertyWithAugmentTest() throws Exception {
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"
215 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\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"
221 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
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());
230 public void builderTemplateGenerateToStringWithPropertyWithAugmentTest() throws Exception {
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"
236 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\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"
242 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
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());
252 public void builderTemplateGenerateToStringWithMorePropertiesWithAugmentTest() throws Exception {
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"
258 + " * @param <T$$> implementation type, which has to also implement AugmentationHolder interface\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"
264 + "static <T$$ extends test.test & AugmentationHolder<test.test>> String bindingToString(final @NonNull"
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());
275 public void builderTemplateGenerateToEqualsComparingOrderTest() {
276 final EffectiveModelContext context = YangParserTestUtils.parseYangResource(
278 final List<Type> types = new DefaultBindingGenerator().generateTypes(context);
279 final BuilderTemplate bt = BuilderGenerator.templateForType((GeneratedType) types.get(19));
281 final List<String> sortedProperties = bt.properties.stream()
282 .sorted(ByTypeMemberComparator.getInstance())
283 .map(BuilderGeneratedProperty::getName)
284 .collect(Collectors.toList());
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",
292 // string, binary, bits
293 "idBinary", "idBinaryDef", "idBits", "idBitsDef", "idGroupLeafString", "idLeafrefContainer1",
294 "idLeafrefContainer1Def", "idString", "idStringDef",
295 // instance identifier
296 "idInstanceIdentifier", "idInstanceIdentifierDef",
298 "idContainer1", "idContainer2", "idEnumeration", "idEnumerationDef",
299 "idGroupContainer", "idList", "idUnion", "idUnionDef"), sortedProperties);
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();
307 doReturn(impls).when(genType).getImplements();
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();
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);
322 doReturn(listMethodSign).when(genType).getMethodDefinitions();
324 final List<Type> impls = new ArrayList<>();
325 doReturn(impls).when(genType).getImplements();
329 private static CharSequence genToString(final GeneratedType genType) {
330 return new InterfaceTemplate(genType).generateBindingToString();
333 private static CharSequence genHashCode(final GeneratedType genType) {
334 return new InterfaceTemplate(genType).generateBindingHashCode();
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();
343 final List<MethodSignature> listMethodSign = new ArrayList<>();
344 final MethodSignature methSign = mockMethSign(methodeName);
345 listMethodSign.add(methSign);
346 doReturn(listMethodSign).when(genType).getMethodDefinitions();
348 final List<Type> impls = new ArrayList<>();
349 doReturn(impls).when(genType).getImplements();
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();