22040d3b365590fff19d7eae43af64928221d07f
[yangtools.git] /
1 /*
2  * Copyright (c) 2020 Pantheon Technologies, 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.yangtools.binding.codegen;
9
10 import static org.hamcrest.CoreMatchers.containsString;
11 import static org.hamcrest.CoreMatchers.not;
12 import static org.hamcrest.MatcherAssert.assertThat;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertNotNull;
15 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.DOUBLE_TAB;
16 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.TAB;
17 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.TRIPLE_TAB;
18 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.doubleTab;
19 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.getFiles;
20 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.tab;
21 import static org.opendaylight.yangtools.binding.codegen.FileSearchUtil.tripleTab;
22
23 import java.io.File;
24 import java.nio.file.Files;
25 import java.nio.file.Path;
26 import java.util.List;
27 import java.util.Map;
28 import org.junit.After;
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.opendaylight.yangtools.binding.contract.Naming;
32 import org.opendaylight.yangtools.binding.model.api.GeneratedType;
33 import org.opendaylight.yangtools.binding.model.api.ParameterizedType;
34 import org.opendaylight.yangtools.binding.model.api.Type;
35 import org.opendaylight.yangtools.binding.model.ri.Types;
36
37 public class SpecializingLeafrefTest extends BaseCompilationTest {
38     private static final ParameterizedType SET_STRING_TYPE  = Types.setTypeFor(Types.STRING);
39
40     public static final String BAR_CONT = "BarCont";
41     public static final String BOOLEAN_CONT = "BooleanCont";
42
43     private static final String BAR_LST = "BarLst";
44     private static final String BAZ_GRP = "BazGrp";
45     private static final String FOO_GRP = "FooGrp";
46     private static final String RESOLVED_LEAF_GRP = "ResolvedLeafGrp";
47     private static final String RESOLVED_LEAFLIST_GRP = "ResolvedLeafListGrp";
48     private static final String TRANSITIVE_GROUP = "TransitiveGroup";
49     private static final String UNRESOLVED_GROUPING = "UnresolvedGrouping";
50
51     private static final String GET_LEAF1_NAME = "getLeaf1";
52     private static final String GET_LEAFLIST1_NAME = "getLeafList1";
53
54     private static final String GET_LEAF1_TYPE_OBJECT = "    Object getLeaf1();";
55     private static final String GET_LEAF1_TYPE_STRING = "    String getLeaf1();";
56     private static final String GET_LEAFLIST1_WILDCARD = "    @Nullable Set<?> getLeafList1();";
57     private static final String GET_LEAFLIST1_STRING = "    @Nullable Set<String> getLeafList1();";
58     private static final String GET_LEAFLIST1_DECLARATION = " getLeafList1();";
59     private static final String GET_LEAF1_DECLARATION = " getLeaf1();";
60
61     private static final char CLOSING_METHOD_BRACE = '}';
62     private static final String TAB_CLOSING_METHOD_BRACE = TAB + CLOSING_METHOD_BRACE;
63     private static final String DTAB_CLOSING_METHOD_BRACE = DOUBLE_TAB + CLOSING_METHOD_BRACE;
64
65     private static final String FOO_GRP_REF = "FooGrp";
66     private static final String RESOLVED_LEAF_GRP_REF = "ResolvedLeafGrp";
67     private static final String UNRESOLVED_GROUPING_REF = "UnresolvedGrouping";
68
69     private static final String LEAF2_ASSIGNMENT = "this._leaf2 = arg.getLeaf2();";
70
71     private static final String TAB_FIELDS_FROM_SIGNATURE = TAB + "public void fieldsFrom(final Grouping arg) {";
72     private static final String TTAB_SET_IS_VALID_ARG_TRUE = TRIPLE_TAB + "isValidArg = true;";
73     private static final String DTAB_INIT_IS_VALID_ARG_FALSE = DOUBLE_TAB + "boolean isValidArg = false;";
74
75     private File sourcesOutputDir;
76     private File compiledOutputDir;
77     private List<GeneratedType> types;
78     private Map<String, File> files;
79
80     @Before
81     public void before() {
82         sourcesOutputDir = CompilationTestUtils.generatorOutput("mdsal426");
83         compiledOutputDir = CompilationTestUtils.compilerOutput("mdsal426");
84         types = generateTestSources("/compilation/mdsal426", sourcesOutputDir);
85         CompilationTestUtils.testCompilation(sourcesOutputDir, compiledOutputDir);
86         files = getFiles(sourcesOutputDir);
87     }
88
89     @After
90     public void after() {
91         CompilationTestUtils.cleanUp(sourcesOutputDir, compiledOutputDir);
92     }
93
94     @Test
95     public void testGroupingWithUnresolvedLeafRefs() throws Exception {
96         verifyReturnType(FOO_GRP, GET_LEAF1_NAME, Types.objectType());
97         verifyReturnType(FOO_GRP, GET_LEAFLIST1_NAME, Types.setTypeWildcard());
98
99         final String content = getFileContent(FOO_GRP);
100
101         assertThat(content, containsString(GET_LEAF1_TYPE_OBJECT));
102         assertThat(content, containsString(GET_LEAFLIST1_WILDCARD));
103     }
104
105     @Test
106     public void testLeafLeafrefPointsLeaf() throws Exception {
107         verifyReturnType(RESOLVED_LEAF_GRP, GET_LEAF1_NAME, Types.STRING);
108
109         final String content = getFileContent(RESOLVED_LEAF_GRP);
110
111         assertThat(content, containsString(GET_LEAF1_TYPE_STRING));
112     }
113
114     @Test
115     public void testLeafLeafrefPointsLeafList() throws Exception {
116         verifyReturnType(RESOLVED_LEAFLIST_GRP, GET_LEAF1_NAME, Types.STRING);
117
118         final String content = getFileContent(RESOLVED_LEAF_GRP);
119
120         assertThat(content, containsString(GET_LEAF1_TYPE_STRING));
121     }
122
123     @Test
124     public void testLeafListLeafrefPointsLeaf() throws Exception {
125         verifyReturnType(RESOLVED_LEAF_GRP, GET_LEAFLIST1_NAME, SET_STRING_TYPE);
126
127         final String content = getFileContent(RESOLVED_LEAF_GRP);
128
129         assertOverriddenGetter(content, GET_LEAFLIST1_STRING);
130     }
131
132     @Test
133     public void testLeafListLeafrefPointsLeafList() throws Exception {
134         verifyReturnType(RESOLVED_LEAFLIST_GRP, GET_LEAFLIST1_NAME, SET_STRING_TYPE);
135
136         final String content = getFileContent(RESOLVED_LEAFLIST_GRP);
137
138         assertOverriddenGetter(content, GET_LEAFLIST1_STRING);
139     }
140
141     @Test
142     public void testGroupingWhichInheritUnresolvedLeafrefAndDoesNotDefineIt() throws Exception {
143         verifyMethodAbsence(TRANSITIVE_GROUP, GET_LEAF1_NAME);
144         verifyMethodAbsence(TRANSITIVE_GROUP, GET_LEAFLIST1_NAME);
145
146         final String content = getFileContent(TRANSITIVE_GROUP);
147
148         assertThat(content, not(containsString(GET_LEAF1_DECLARATION)));
149         assertThat(content, not(containsString(GET_LEAFLIST1_DECLARATION)));
150     }
151
152     @Test
153     public void testLeafrefWhichPointsBoolean() throws Exception {
154         verifyReturnType(UNRESOLVED_GROUPING, GET_LEAF1_NAME, Types.objectType());
155         verifyReturnType(BOOLEAN_CONT, GET_LEAF1_NAME, Types.BOOLEAN);
156
157         final String unresolvedGrouping = getFileContent(UNRESOLVED_GROUPING);
158         final String booleanCont = getFileContent(BOOLEAN_CONT);
159
160         assertNotOverriddenGetter(unresolvedGrouping, GET_LEAF1_TYPE_OBJECT);
161         assertThat(booleanCont, containsString(GET_LEAF1_DECLARATION));
162     }
163
164     @Test
165     public void testGroupingsUsageWhereLeafrefAlreadyResolved() throws Exception {
166         leafList1AndLeaf1Absence(BAR_CONT);
167         leafList1AndLeaf1Absence(BAR_LST);
168         leafList1AndLeaf1Absence(BAZ_GRP);
169     }
170
171     private void leafList1AndLeaf1Absence(final String typeName) throws Exception {
172         verifyMethodAbsence(typeName, GET_LEAF1_NAME);
173         verifyMethodAbsence(typeName, GET_LEAFLIST1_NAME);
174
175         final String content = getFileContent(typeName);
176
177         assertThat(content, not(containsString(GET_LEAF1_DECLARATION)));
178         assertThat(content, not(containsString(GET_LEAFLIST1_DECLARATION)));
179     }
180
181     private static void assertNotOverriddenGetter(final String fileContent, final String getterString) {
182         assertThat(fileContent, not(containsString("@Override" + System.lineSeparator() + getterString)));
183         assertThat(fileContent, containsString(getterString));
184     }
185
186     private static void assertOverriddenGetter(final String fileContent, final String getterString) {
187         assertThat(fileContent, containsString("@Override" + System.lineSeparator() + getterString));
188     }
189
190     @Test
191     public void barContBuilderDataObjectTest() throws Exception {
192         final File file = files.get(getJavaBuilderFileName(BAR_CONT));
193         final String content = Files.readString(file.toPath());
194
195         barContBuilderConstructorResolvedLeafGrpTest(file, content);
196         barContBuilderConstructorFooGrpTest(file, content);
197         barContBuilderFieldsFromTest(file, content);
198     }
199
200     private static void barContBuilderConstructorResolvedLeafGrpTest(final File file, final String content) {
201         FileSearchUtil.assertFileContainsConsecutiveLines(file, content,
202                 tab("public BarContBuilder(" + RESOLVED_LEAF_GRP_REF + " arg) {"),
203                 doubleTab("this._leaf1 = arg.getLeaf1();"),
204                 doubleTab("this._leafList1 = arg.getLeafList1();"),
205                 doubleTab("this._name = arg.getName();"),
206                 doubleTab(LEAF2_ASSIGNMENT),
207                 TAB_CLOSING_METHOD_BRACE);
208     }
209
210     private static void barContBuilderFieldsFromTest(final File file, final String content) {
211         FileSearchUtil.assertFileContainsConsecutiveLines(file, content,
212                 TAB_FIELDS_FROM_SIGNATURE,
213                 DTAB_INIT_IS_VALID_ARG_FALSE,
214                 doubleTab("if (arg instanceof " + FOO_GRP_REF + " castArg) {"),
215                 tripleTab("this._leaf1 = CodeHelpers.checkFieldCast(String.class, \"leaf1\", castArg.getLeaf1());"),
216                 tripleTab("this._leafList1 = CodeHelpers.checkSetFieldCast(String.class, \"leafList1\", "
217                     + "castArg.getLeafList1());"),
218                 tripleTab("this._leaf2 = castArg.getLeaf2();"),
219                 TTAB_SET_IS_VALID_ARG_TRUE,
220                 DTAB_CLOSING_METHOD_BRACE,
221                 doubleTab("if (arg instanceof " + RESOLVED_LEAF_GRP_REF + " castArg) {"),
222                 tripleTab("this._name = castArg.getName();"),
223                 TTAB_SET_IS_VALID_ARG_TRUE,
224                 DTAB_CLOSING_METHOD_BRACE,
225                 doubleTab("CodeHelpers.validValue(isValidArg, arg, \"[" + FOO_GRP_REF + ", " + RESOLVED_LEAF_GRP_REF
226                     + "]\");"),
227                 TAB_CLOSING_METHOD_BRACE);
228     }
229
230     private static void barContBuilderConstructorFooGrpTest(final File file, final String content) {
231         FileSearchUtil.assertFileContainsConsecutiveLines(file, content,
232                 tab("public BarContBuilder(" + FOO_GRP_REF + " arg) {"),
233                 doubleTab("this._leaf1 = CodeHelpers.checkFieldCast(String.class, \"leaf1\", "
234                     + "arg.getLeaf1());"),
235                 doubleTab("this._leafList1 = CodeHelpers.checkSetFieldCast(String.class, \"leafList1\", "
236                     + "arg.getLeafList1());"),
237                 doubleTab(LEAF2_ASSIGNMENT),
238                 TAB_CLOSING_METHOD_BRACE);
239     }
240
241     @Test
242     public void booleanContBuilderDataObjectTest() throws Exception {
243         final File file = files.get(getJavaBuilderFileName(BOOLEAN_CONT));
244         final String content = Files.readString(file.toPath());
245
246         booleanContBuilderFieldsFromTest(file, content);
247         booleanContBuilderConstructorTest(file, content);
248     }
249
250     private static void booleanContBuilderFieldsFromTest(final File file, final String content) {
251         FileSearchUtil.assertFileContainsConsecutiveLines(file, content,
252                 TAB_FIELDS_FROM_SIGNATURE,
253                 DTAB_INIT_IS_VALID_ARG_FALSE,
254                 doubleTab("if (arg instanceof " + UNRESOLVED_GROUPING_REF + " castArg) {"),
255                 tripleTab("this._leaf1 = CodeHelpers.checkFieldCast(Boolean.class, \"leaf1\", castArg.getLeaf1());"),
256                 TTAB_SET_IS_VALID_ARG_TRUE,
257                 DTAB_CLOSING_METHOD_BRACE,
258                 doubleTab("CodeHelpers.validValue(isValidArg, arg, \"[" + UNRESOLVED_GROUPING_REF + "]\");"),
259                 TAB_CLOSING_METHOD_BRACE);
260     }
261
262     private static void booleanContBuilderConstructorTest(final File file, final String content) {
263         FileSearchUtil.assertFileContainsConsecutiveLines(file, content,
264                 tab("public BooleanContBuilder(" + UNRESOLVED_GROUPING_REF + " arg) {"),
265                 doubleTab("this._leaf1 = CodeHelpers.checkFieldCast(Boolean.class, \"leaf1\", "
266                     + "arg.getLeaf1());"),
267                 TAB_CLOSING_METHOD_BRACE);
268     }
269
270     private static String getJavaFileName(final String name) {
271         return name + ".java";
272     }
273
274     private static String getJavaBuilderFileName(final String name) {
275         return getJavaFileName(name + Naming.BUILDER_SUFFIX);
276     }
277
278     private String getFileContent(final String fileName) throws Exception {
279         final File file = files.get(getJavaFileName(fileName));
280         assertNotNull(Files.lines(file.toPath()).findFirst());
281         final String content = Files.readString(Path.of(file.getAbsolutePath()));
282         assertNotNull(content);
283         return content;
284     }
285
286     private void verifyMethodAbsence(final String typeName, final String getterName) {
287         verifyReturnType(typeName, getterName, null);
288     }
289
290     private void verifyReturnType(final String typeName, final String getterName, final Type returnType) {
291         final GeneratedType generated = typeByName(types, typeName);
292         assertNotNull(generated);
293         assertEquals(returnType, returnTypeByMethodName(generated, getterName));
294     }
295
296     private static GeneratedType typeByName(final List<GeneratedType> types, final String name) {
297         for (var type : types) {
298             if (type.getName().equals(name)) {
299                 return type;
300             }
301         }
302         return null;
303     }
304
305     private static Type returnTypeByMethodName(final GeneratedType type, final String name) {
306         for (var m : type.getMethodDefinitions()) {
307             if (m.getName().equals(name)) {
308                 return m.getReturnType();
309             }
310         }
311         return null;
312     }
313 }