BUG-580: Improved parsing.
[yangtools.git] / code-generator / binding-generator-impl / src / test / java / org / opendaylight / yangtools / sal / binding / generator / impl / RefineTest.java
1 /*
2  * Copyright (c) 2013 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.yangtools.sal.binding.generator.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertTrue;
14
15 import com.google.common.collect.Lists;
16 import com.google.common.collect.Maps;
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.FileNotFoundException;
20 import java.io.InputStream;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.util.ArrayList;
26 import java.util.Date;
27 import java.util.GregorianCalendar;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Set;
31 import org.junit.Ignore;
32 import org.junit.Test;
33 import org.opendaylight.yangtools.yang.common.QName;
34 import org.opendaylight.yangtools.yang.model.api.MustDefinition;
35 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
36 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
37 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
38 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
39 import org.opendaylight.yangtools.yang.parser.builder.impl.AnyXmlBuilder;
40 import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder;
41 import org.opendaylight.yangtools.yang.parser.builder.impl.ConstraintsBuilder;
42 import org.opendaylight.yangtools.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
43 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
44 import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
45 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
46 import org.opendaylight.yangtools.yang.parser.util.RefineHolder;
47 import org.opendaylight.yangtools.yang.parser.util.RefineUtils;
48
49 //Test for class RefineUtils
50 public class RefineTest {
51
52     private static List<File> testModels = new ArrayList<>();
53
54     private void loadTestResources() throws URISyntaxException {
55         final File listModelFile = new File(RefineTest.class.getResource("/refine.yang").toURI());
56         testModels.add(listModelFile);
57     }
58
59     private void findUnknownNode(DataSchemaNodeBuilder childNode, String unknownNodeValue, String unknownNodeName) {
60         List<UnknownSchemaNodeBuilder> unknownSchemaNodesBuilder = childNode.getUnknownNodes();
61         boolean refinedUnknownNodeLflstFound = false;
62
63         for (UnknownSchemaNodeBuilder unknownSchemaNodeBuilders : unknownSchemaNodesBuilder) {
64             if (unknownSchemaNodeBuilders.getNodeType().getLocalName().equals(unknownNodeName)
65                     && unknownSchemaNodeBuilders.getQName().getLocalName().equals(unknownNodeValue)) {
66                 refinedUnknownNodeLflstFound = true;
67             }
68         }
69         assertTrue("Unknown node " + unknownNodeName + " with value " + unknownNodeValue + " wasn't found.",
70                 refinedUnknownNodeLflstFound);
71     }
72
73     private void findMustConstraint(ConstraintsBuilder conDef, String mustValue) {
74         boolean mustLflstFound = false;
75         for (MustDefinition mustDef : conDef.getMustDefinitions()) {
76             if (mustDef.toString().equals(mustValue)) {
77                 mustLflstFound = true;
78                 break;
79             }
80         }
81         assertTrue("Must element in 'lflst' is missing.", mustLflstFound);
82     }
83
84     // FIXME: rework test
85     @Ignore
86     @Test
87     public void usesInGroupingDependenciesTest() throws URISyntaxException {
88         loadTestResources();
89         assertEquals("Incorrect number of test files.", 1, testModels.size());
90
91         Set<UsesNodeBuilder> usesNodeBuilders = getModuleBuilder().getUsesNodeBuilders();
92         List<RefineHolder> refineHolders = null;
93         Set<DataSchemaNodeBuilder> dataSchemaNodeBuilders = null;
94         for (UsesNodeBuilder usesNodeBuilder : usesNodeBuilders) {
95             if (usesNodeBuilder.getGroupingPathAsString().equals("grp")) {
96                 refineHolders = usesNodeBuilder.getRefines();
97                 dataSchemaNodeBuilders = usesNodeBuilder.getParent().getChildNodeBuilders();
98                 break;
99             }
100         }
101
102         assertNotNull("List of refine holders wasn't initialized.", refineHolders);
103         assertEquals("Incorrect number of refine holders", 4, refineHolders.size());
104
105         checkLflstRefineHolderAndSchemaNodeBuilder("lflst", refineHolders, dataSchemaNodeBuilders);
106         checkChcRefineHolderAndSchemaNodeBuilder("chc", refineHolders, dataSchemaNodeBuilders);
107         checkChc2RefineHolderAndSchemaNodeBuilder("chc2", refineHolders, dataSchemaNodeBuilders);
108         checkAnyXmlRefineHolderAndSchemaNodeBuilder("data", refineHolders, dataSchemaNodeBuilders);
109     }
110
111     private ModuleBuilder getModuleBuilder() {
112         Class<YangParserImpl> cl = YangParserImpl.class;
113
114         YangParserImpl yangParserImpl = null;
115         yangParserImpl = new YangParserImpl();
116         assertNotNull("Instance of YangParserImpl isn't created", yangParserImpl);
117
118         Method methodResolveModuleBuilders = null;
119         try {
120             methodResolveModuleBuilders = cl.getDeclaredMethod("resolveModuleBuilders", java.util.Collection.class, SchemaContext.class);
121         } catch (NoSuchMethodException | SecurityException e1) {
122         }
123         assertNotNull("The method resolveModuleBuilders cannot be found", methodResolveModuleBuilders);
124
125         final Map<InputStream, File> inputStreams = Maps.newHashMap();
126
127         for (final File yangFile : testModels) {
128             try {
129                 inputStreams.put(new FileInputStream(yangFile), yangFile);
130             } catch (FileNotFoundException e) {
131             }
132         }
133         assertEquals("Map with input streams contains incorrect number of files.", 1, inputStreams.size());
134
135         Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
136         Map<String, Map<Date, ModuleBuilder>> modules = null;
137         try {
138             methodResolveModuleBuilders.setAccessible(true);
139             modules = (Map<String, Map<Date, ModuleBuilder>>) methodResolveModuleBuilders.invoke(yangParserImpl,
140                     Lists.newArrayList(inputStreams.keySet()), null);
141         } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
142             e.printStackTrace();
143         }
144         assertEquals("Map with modules contains incorrect number of modules", 1, modules.size());
145         Map<Date, ModuleBuilder> mapWithModuleBuilder = modules.get("module-refine");
146         assertEquals("Map with module builders contains incorrect number of modules", 1, mapWithModuleBuilder.size());
147         Date date = new GregorianCalendar(2013, GregorianCalendar.SEPTEMBER, 11).getTime();
148         ModuleBuilder moduleBuilder = mapWithModuleBuilder.get(date);
149         assertNotNull("Module builder wasn't find", moduleBuilder);
150         return moduleBuilder;
151     }
152
153     private void checkAnyXmlRefineHolderAndSchemaNodeBuilder(String string, List<RefineHolder> refineHolders,
154             Set<DataSchemaNodeBuilder> dataSchemaNodeBuilders) {
155         RefineHolder refHolderData = getRefineHolder("data", refineHolders);
156
157         QName qname = createQname();
158         DataSchemaNodeBuilder builderData = new AnyXmlBuilder("module", 4, qname, createSchemaPath(qname));
159
160         assertNotNull("Refine holder data wasn't initialized.", refHolderData);
161         RefineUtils.refineAnyxml((AnyXmlBuilder) builderData, refHolderData);
162
163         // data node
164         ConstraintsBuilder conDefData = builderData.getConstraints();
165         assertFalse("'data' has incorrect value for 'mandatory'", conDefData.isMandatory());
166
167         String unknownNodeDataValue = "some value from data";
168         String unknownNodeDataName = "new-subnode-data";
169         findUnknownNode(builderData, unknownNodeDataValue, unknownNodeDataName);
170         findMustConstraint(conDefData, "something-else = 9");
171
172     }
173
174     private void checkChc2RefineHolderAndSchemaNodeBuilder(String nodeName, List<RefineHolder> refineHolders,
175             Set<DataSchemaNodeBuilder> dataSchemaNodeBuilders) {
176         RefineHolder refHolderChc2 = getRefineHolder("chc2", refineHolders);
177
178         QName qname = createQname();
179         List<QName> path = Lists.newArrayList(qname);
180         DataSchemaNodeBuilder builderChc2 = new ChoiceBuilder("module", 4, qname, new SchemaPath(path, true));
181         assertNotNull("Refine holder chc2 wasn't initialized.", refHolderChc2);
182
183         RefineUtils.refineChoice((ChoiceBuilder) builderChc2, refHolderChc2);
184
185         // chc2 node
186         ConstraintsBuilder conDefChc2 = builderChc2.getConstraints();
187         assertFalse("'chc2' has incorrect value for 'mandatory'", conDefChc2.isMandatory());
188     }
189
190     private void checkChcRefineHolderAndSchemaNodeBuilder(String nodeName, List<RefineHolder> refineHolders,
191             Set<DataSchemaNodeBuilder> dataSchemaNodeBuilders) {
192         RefineHolder refHolderChc = getRefineHolder("chc", refineHolders);
193
194         QName qname = createQname();
195         List<QName> path = Lists.newArrayList(qname);
196         DataSchemaNodeBuilder builderChc = new ChoiceBuilder("module", 4, qname, new SchemaPath(path, true));
197
198         assertNotNull("Refine holder chc wasn't initialized.", refHolderChc);
199         assertNotNull("Data schema node builder chc wasn't initialized.", builderChc);
200         RefineUtils.refineChoice((ChoiceBuilder) builderChc, refHolderChc);
201
202         ChoiceBuilder choiceBuilder = null;
203         if (builderChc instanceof ChoiceBuilder) {
204             choiceBuilder = (ChoiceBuilder) builderChc;
205         }
206         assertNotNull("Choice node chc isn't of type ChoiceBuilder", choiceBuilder);
207         assertEquals("chc node has incorrect default node.", "first", choiceBuilder.getDefaultCase());
208         String unknownNodeChcValue = "some value from chc";
209         String unknownNodeChcName = "new-subnode-chc";
210         findUnknownNode(choiceBuilder, unknownNodeChcValue, unknownNodeChcName);
211     }
212
213     private void checkLflstRefineHolderAndSchemaNodeBuilder(String nodeName, List<RefineHolder> refineHolders,
214             Set<DataSchemaNodeBuilder> dataSchemaNodeBuilders) {
215         RefineHolder refHolderLflst = getRefineHolder(nodeName, refineHolders);
216
217         QName qname = createQname();
218         DataSchemaNodeBuilder builderLflst = new LeafListSchemaNodeBuilder("module", 4, qname, createSchemaPath(qname));
219
220         assertNotNull("Refine holder " + nodeName + " wasn't initialized.", refHolderLflst);
221         assertNotNull("Data schema node builder " + nodeName + " wasn't initialized.", builderLflst);
222         RefineUtils.refineLeafList((LeafListSchemaNodeBuilder) builderLflst, refHolderLflst);
223         // lflst node
224
225         ConstraintsBuilder conDefLflst = builderLflst.getConstraints();
226         assertEquals("Max elements number in " + nodeName + " is incorrect.", new Integer(64),
227                 conDefLflst.getMaxElements());
228         assertEquals("Max elements number in " + nodeName + " is incorrect.", new Integer(32),
229                 conDefLflst.getMinElements());
230
231         findMustConstraint(conDefLflst, "new = 57");
232
233         boolean mustLflstFound = false;
234         for (MustDefinition mustDef : conDefLflst.getMustDefinitions()) {
235             if (mustDef.toString().equals("new = 57")) {
236                 mustLflstFound = true;
237                 break;
238             }
239         }
240         assertTrue("Must element in " + nodeName + " is missing.", mustLflstFound);
241
242         findUnknownNode(builderLflst, "some value from " + nodeName, "new-subnode");
243
244     }
245
246     private RefineHolder getRefineHolder(String refHolderName, List<RefineHolder> refineHolders) {
247         for (RefineHolder refineHolder : refineHolders) {
248             if (refineHolder.getName().equals(refHolderName)) {
249                 return refineHolder;
250             }
251         }
252         return null;
253     }
254
255     private QName createQname() {
256         QName qname = null;
257         boolean uriCreated = false;
258         try {
259             qname = new QName(new URI("uri"), "q name");
260             uriCreated = true;
261         } catch (URISyntaxException e) {
262         }
263         assertTrue("Qname wasn't created sucessfully.", uriCreated);
264         return qname;
265     }
266
267     private SchemaPath createSchemaPath(QName qname) {
268         List<QName> qnames = new ArrayList<>();
269         qnames.add(createQname());
270         return new SchemaPath(qnames, true);
271     }
272
273 }