Added getParent() method to DataSchemaNode and DataNodeContainer. Fixed Bugs.
[mdsal.git] / code-generator / binding-java-api-generator / src / test / java / org / opendaylight / yangtools / sal / java / api / generator / test / CompilationTest.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.java.api.generator.test;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertTrue;
12
13 import java.io.File;
14 import java.io.FileNotFoundException;
15 import java.lang.annotation.Annotation;
16 import java.lang.reflect.Method;
17 import java.lang.reflect.ParameterizedType;
18 import java.lang.reflect.WildcardType;
19 import java.net.URL;
20 import java.net.URLClassLoader;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.HashSet;
24 import java.util.List;
25 import java.util.Set;
26
27 import javax.tools.JavaCompiler;
28 import javax.tools.JavaFileObject;
29 import javax.tools.StandardJavaFileManager;
30 import javax.tools.ToolProvider;
31
32 import org.junit.Before;
33 import org.junit.BeforeClass;
34 import org.junit.Test;
35 import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
36 import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
37 import org.opendaylight.yangtools.sal.binding.model.api.Type;
38 import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
39 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
40 import org.opendaylight.yangtools.yang.model.api.Module;
41 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
42 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
43
44 /**
45  * Test correct code generation.
46  *
47  */
48 public class CompilationTest {
49     private static final String FS = File.separator;
50     private static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
51     private static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
52     private static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
53     private static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
54     private static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
55
56     private static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
57
58     private static final String TEST_PATH = "target" + FS + "test";
59     private static final File TEST_DIR = new File(TEST_PATH);
60
61     private static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
62     private static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
63     private static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
64     private static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
65
66     private YangParserImpl parser;
67     private BindingGenerator bindingGenerator;
68     private JavaCompiler compiler;
69     private StandardJavaFileManager fileManager;
70
71     @BeforeClass
72     public static void createTestDirs() {
73         if (TEST_DIR.exists()) {
74             deleteTestDir(TEST_DIR);
75         }
76         assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
77         assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
78     }
79
80     @Before
81     public void init() {
82         parser = new YangParserImpl();
83         bindingGenerator = new BindingGeneratorImpl();
84         compiler = ToolProvider.getSystemJavaCompiler();
85         fileManager = compiler.getStandardFileManager(null, null, null);
86     }
87
88     /**
89      * Method to clean resources. It is manually called at the end of each test
90      * instead of marking it with @After annotation to prevent removing
91      * generated code if test fails.
92      */
93     public void cleanUp(File... resourceDirs) {
94         for (File resourceDir : resourceDirs) {
95             if (resourceDir.exists()) {
96                 deleteTestDir(resourceDir);
97             }
98         }
99     }
100
101     @Test
102     public void testListGeneration() throws Exception {
103         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "list-gen");
104         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
105         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "list-gen");
106         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
107
108         final List<File> sourceFiles = getSourceFiles("/compilation/list-gen");
109         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
110         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
111         final List<Type> types = bindingGenerator.generateTypes(context);
112         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
113         generator.generateToFile(sourcesOutputDir);
114
115         // Test if all sources are generated
116         File parent = new File(sourcesOutputDir, NS_TEST);
117         assertEquals(6, parent.listFiles().length);
118         File keyArgs = new File(parent, "KeyArgs.java");
119         File links = new File(parent, "Links.java");
120         File linksBuilder = new File(parent, "LinksBuilder.java");
121         File linksKey = new File(parent, "LinksKey.java");
122         File testData = new File(parent, "TestData.java");
123         assertTrue(keyArgs.exists());
124         assertTrue(links.exists());
125         assertTrue(linksBuilder.exists());
126         assertTrue(linksKey.exists());
127         assertTrue(testData.exists());
128
129         parent = new File(sourcesOutputDir, NS_TEST + FS + "links");
130         assertEquals(7, parent.listFiles().length);
131         File level = new File(parent, "Level.java");
132         File linkGroup = new File(parent, "LinkGroup.java");
133         File node = new File(parent, "Node.java");
134         File nodeBuilder = new File(parent, "NodeBuilder.java");
135         File nodeList = new File(parent, "NodeList.java");
136         File nodeListBuilder = new File(parent, "NodeListBuilder.java");
137         File nodesType = new File(parent, "NodesType.java");
138         assertTrue(level.exists());
139         assertTrue(linkGroup.exists());
140         assertTrue(node.exists());
141         assertTrue(nodeBuilder.exists());
142         assertTrue(nodeList.exists());
143         assertTrue(nodeListBuilder.exists());
144         assertTrue(nodesType.exists());
145
146         // Test if sources are compilable
147         testCompilation(sourcesOutputDir, compiledOutputDir);
148
149         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
150         Class<?> keyArgsClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.KeyArgs", true, loader);
151         Class<?> linksClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Links", true, loader);
152         Class<?> linksKeyClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksKey", true, loader);
153
154         // Test generated 'grouping key-args'
155         try {
156             assertTrue(keyArgsClass.isInterface());
157             assertEquals(3, keyArgsClass.getDeclaredMethods().length);
158
159             Method getId = keyArgsClass.getMethod("getId");
160             assertEquals(Byte.class, getId.getReturnType());
161             Method getName = keyArgsClass.getMethod("getName");
162             assertEquals(String.class, getName.getReturnType());
163             Method getSize = keyArgsClass.getMethod("getSize");
164             assertEquals(Integer.class, getSize.getReturnType());
165         } catch (NoSuchMethodException e) {
166             throw new AssertionError("Required method not found in " + keyArgsClass, e);
167         }
168
169         // test generated 'list links'
170         assertTrue(linksClass.isInterface());
171         // FIXME: anyxml
172         assertEquals(5, linksClass.getDeclaredMethods().length);
173         testImplementIfc(linksClass, keyArgsClass);
174
175         // Test list key constructor arguments ordering
176         try {
177             linksKeyClass.getConstructor(Byte.class, String.class, Integer.class);
178         } catch (NoSuchMethodException e) {
179             throw new AssertionError("Parameters of list key constructor are not properly ordered");
180         }
181
182         cleanUp(sourcesOutputDir, compiledOutputDir);
183     }
184
185     @Test
186     public void testAugmentUnderUsesGeneration() throws Exception {
187         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-under-uses");
188         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
189         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-under-uses");
190         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
191
192         final List<File> sourceFiles = getSourceFiles("/compilation/augment-under-uses");
193         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
194         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
195         final List<Type> types = bindingGenerator.generateTypes(context);
196         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
197         generator.generateToFile(sourcesOutputDir);
198
199         // Test if all sources were generated from 'module foo'
200         File parent = new File(sourcesOutputDir, NS_FOO);
201         assertEquals(7, parent.listFiles().length);
202         assertTrue(new File(parent, "Object.java").exists());
203         assertTrue(new File(parent, "OpenObject.java").exists());
204         assertTrue(new File(parent, "ExplicitRouteObject.java").exists());
205         assertTrue(new File(parent, "PathKeySubobject.java").exists());
206
207         parent = new File(parent, "object");
208         assertEquals(2, parent.listFiles().length);
209         assertTrue(new File(parent, "Nodes.java").exists());
210         assertTrue(new File(parent, "NodesBuilder.java").exists());
211
212         parent = new File(sourcesOutputDir, NS_FOO + FS + "open");
213         assertEquals(1, parent.listFiles().length);
214
215         parent = new File(parent, "object");
216         assertEquals(3, parent.listFiles().length);
217         assertTrue(new File(parent, "Nodes1.java").exists());
218         assertTrue(new File(parent, "Nodes1Builder.java").exists());
219
220         parent = new File(parent, "nodes");
221         assertEquals(2, parent.listFiles().length);
222         assertTrue(new File(parent, "Links.java").exists());
223         assertTrue(new File(parent, "LinksBuilder.java").exists());
224
225         parent = new File(sourcesOutputDir, NS_FOO + FS + "explicit");
226         assertEquals(1, parent.listFiles().length);
227         parent = new File(parent, "route");
228         assertEquals(1, parent.listFiles().length);
229         parent = new File(parent, "object");
230         assertEquals(3, parent.listFiles().length);
231         assertTrue(new File(parent, "Subobjects.java").exists());
232         assertTrue(new File(parent, "SubobjectsBuilder.java").exists());
233
234         parent = new File(parent, "subobjects");
235         assertEquals(1, parent.listFiles().length);
236         parent = new File(parent, "subobject");
237         assertEquals(1, parent.listFiles().length);
238         parent = new File(parent, "type");
239         assertEquals(3, parent.listFiles().length);
240         assertTrue(new File(parent, "PathKey.java").exists());
241         assertTrue(new File(parent, "PathKeyBuilder.java").exists());
242
243         parent = new File(parent, "path");
244         assertEquals(1, parent.listFiles().length);
245         parent = new File(parent, "key");
246         assertEquals(2, parent.listFiles().length);
247         assertTrue(new File(parent, "PathKey.java").exists());
248         assertTrue(new File(parent, "PathKeyBuilder.java").exists());
249
250         // Test if all sources were generated from 'module bar'
251         parent = new File(sourcesOutputDir, NS_BAR);
252         assertEquals(3, parent.listFiles().length);
253         assertTrue(new File(parent, "BasicExplicitRouteSubobjects.java").exists());
254         assertTrue(new File(parent, "ExplicitRouteSubobjects.java").exists());
255
256         parent = new File(parent, "basic");
257         assertEquals(1, parent.listFiles().length);
258         parent = new File(parent, "explicit");
259         assertEquals(1, parent.listFiles().length);
260         parent = new File(parent, "route");
261         assertEquals(1, parent.listFiles().length);
262
263         parent = new File(parent, "subobjects");
264         assertEquals(2, parent.listFiles().length);
265         assertTrue(new File(parent, "SubobjectType.java").exists());
266
267         parent = new File(parent, "subobject");
268         assertEquals(1, parent.listFiles().length);
269
270         parent = new File(parent, "type");
271         assertEquals(4, parent.listFiles().length);
272         assertTrue(new File(parent, "IpPrefix.java").exists());
273         assertTrue(new File(parent, "IpPrefixBuilder.java").exists());
274         assertTrue(new File(parent, "Label.java").exists());
275         assertTrue(new File(parent, "LabelBuilder.java").exists());
276
277         // Test if sources are compilable
278         testCompilation(sourcesOutputDir, compiledOutputDir);
279
280         cleanUp(sourcesOutputDir, compiledOutputDir);
281     }
282
283     @Test
284     public void testAugmentOfAugmentGeneration() throws Exception {
285         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "aug-of-aug");
286         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
287         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "aug-of-aug");
288         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
289
290         final List<File> sourceFiles = getSourceFiles("/compilation/augment-of-augment");
291         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
292         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
293         final List<Type> types = bindingGenerator.generateTypes(context);
294         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
295         generator.generateToFile(sourcesOutputDir);
296
297         // Test if all sources were generated from 'module foo'
298         File parent = new File(sourcesOutputDir, NS_FOO);
299         assertEquals(6, parent.listFiles().length);
300         File fooListener = new File(parent, "FooListener.java");
301         File pathAttributes = new File(parent, "PathAttributes.java");
302         File update = new File(parent, "Update.java");
303         File updateBuilder = new File(parent, "UpdateBuilder.java");
304         assertTrue(fooListener.exists());
305         assertTrue(pathAttributes.exists());
306         assertTrue(update.exists());
307         assertTrue(updateBuilder.exists());
308
309         parent = new File(sourcesOutputDir, NS_FOO + FS + "path");
310         assertEquals(1, parent.listFiles().length);
311         parent = new File(parent, "attributes");
312         assertEquals(2, parent.listFiles().length);
313         File origin = new File(parent, "Origin.java");
314         File originBuilder = new File(parent, "OriginBuilder.java");
315         assertTrue(origin.exists());
316         assertTrue(originBuilder.exists());
317
318         parent = new File(sourcesOutputDir, NS_FOO + FS + "update");
319         assertEquals(2, parent.listFiles().length);
320         pathAttributes = new File(parent, "PathAttributes.java");
321         File pathAttributesBuilder = new File(parent, "PathAttributesBuilder.java");
322         assertTrue(pathAttributes.exists());
323         assertTrue(pathAttributesBuilder.exists());
324
325         // Test if all sources were generated from 'module bar'
326         parent = new File(sourcesOutputDir, NS_BAR);
327         assertEquals(5, parent.listFiles().length);
328         File destination = new File(parent, "Destination.java");
329         File pathAttributes1 = new File(parent, "PathAttributes1.java");
330         File pathAttributes1Builder = new File(parent, "PathAttributes1Builder.java");
331         assertTrue(destination.exists());
332         assertTrue(pathAttributes1.exists());
333         assertTrue(pathAttributes1Builder.exists());
334
335         parent = new File(sourcesOutputDir, NS_BAR + FS + "destination");
336         assertEquals(2, parent.listFiles().length);
337         File destinationType = new File(parent, "DestinationType.java");
338         assertTrue(destinationType.exists());
339
340         parent = new File(parent, "destination");
341         assertEquals(1, parent.listFiles().length);
342         parent = new File(parent, "type");
343         assertEquals(2, parent.listFiles().length);
344         File destinationIpv4 = new File(parent, "DestinationIp.java");
345         File destinationIpv4Builder = new File(parent, "DestinationIpBuilder.java");
346         assertTrue(destinationIpv4.exists());
347         assertTrue(destinationIpv4Builder.exists());
348
349         parent = new File(sourcesOutputDir, NS_BAR + FS + "update");
350         assertEquals(1, parent.listFiles().length);
351         parent = new File(parent, "path");
352         assertEquals(1, parent.listFiles().length);
353         parent = new File(parent, "attributes");
354         assertEquals(3, parent.listFiles().length);
355         File mpUnreachNlri = new File(parent, "MpUnreachNlri.java");
356         File mpUnreachNlriBuilder = new File(parent, "MpUnreachNlriBuilder.java");
357         assertTrue(mpUnreachNlri.exists());
358         assertTrue(mpUnreachNlriBuilder.exists());
359
360         parent = new File(parent, "mp");
361         assertEquals(1, parent.listFiles().length);
362         parent = new File(parent, "unreach");
363         assertEquals(1, parent.listFiles().length);
364         parent = new File(parent, "nlri");
365         assertEquals(3, parent.listFiles().length);
366         File withdrawnRoutes = new File(parent, "WithdrawnRoutes.java");
367         File withdrawnRoutesBuilder = new File(parent, "WithdrawnRoutesBuilder.java");
368         assertTrue(withdrawnRoutes.exists());
369         assertTrue(withdrawnRoutesBuilder.exists());
370
371         parent = new File(parent, "withdrawn");
372         assertEquals(1, parent.listFiles().length);
373         parent = new File(parent, "routes");
374         assertEquals(1, parent.listFiles().length);
375         destinationType = new File(parent, "DestinationType.java");
376         assertTrue(destinationType.exists());
377
378         // Test if all sources were generated from 'module baz'
379         parent = new File(sourcesOutputDir, NS_BAZ);
380         assertEquals(2, parent.listFiles().length);
381         File linkstateDestination = new File(parent, "LinkstateDestination.java");
382         assertTrue(linkstateDestination.exists());
383
384         parent = new File(sourcesOutputDir, NS_BAZ + FS + "update");
385         assertEquals(1, parent.listFiles().length);
386         parent = new File(parent, "path");
387         assertEquals(1, parent.listFiles().length);
388         parent = new File(parent, "attributes");
389         assertEquals(1, parent.listFiles().length);
390         parent = new File(parent, "mp");
391         assertEquals(1, parent.listFiles().length);
392         parent = new File(parent, "unreach");
393         assertEquals(1, parent.listFiles().length);
394         parent = new File(parent, "nlri");
395         assertEquals(1, parent.listFiles().length);
396         parent = new File(parent, "withdrawn");
397         assertEquals(1, parent.listFiles().length);
398         parent = new File(parent, "routes");
399         assertEquals(1, parent.listFiles().length);
400         parent = new File(parent, "destination");
401         assertEquals(1, parent.listFiles().length);
402         parent = new File(parent, "type");
403         assertEquals(2, parent.listFiles().length);
404         File destinationLinkstate = new File(parent, "DestinationLinkstate.java");
405         File destinationLinkstateBuilder = new File(parent, "DestinationLinkstateBuilder.java");
406         assertTrue(destinationLinkstate.exists());
407         assertTrue(destinationLinkstateBuilder.exists());
408
409         // Test if sources are compilable
410         testCompilation(sourcesOutputDir, compiledOutputDir);
411
412         cleanUp(sourcesOutputDir, compiledOutputDir);
413     }
414
415     @Test
416     public void testLeafReturnTypes() throws Exception {
417         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "leaf-return-types");
418         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
419         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "leaf-return-types");
420         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
421
422         final List<File> sourceFiles = getSourceFiles("/compilation/leaf-return-types");
423         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
424         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
425         final List<Type> types = bindingGenerator.generateTypes(context);
426         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
427         generator.generateToFile(sourcesOutputDir);
428
429         File parent = new File(sourcesOutputDir, NS_TEST);
430         assertTrue(new File(parent, "TestData.java").exists());
431         assertTrue(new File(parent, "Nodes.java").exists());
432         assertTrue(new File(parent, "NodesBuilder.java").exists());
433         assertTrue(new File(parent, "Alg.java").exists());
434
435         // Test if sources are compilable
436         testCompilation(sourcesOutputDir, compiledOutputDir);
437
438         String pkg = BASE_PKG + ".urn.opendaylight.test.rev131008";
439         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
440         Class<?> nodesClass = Class.forName(pkg + ".Nodes", true, loader);
441
442         // Test methods return type
443         byte[] b = new byte[] {};
444         testReturnType(nodesClass, "getIdBinary", b.getClass());
445         testReturnType(nodesClass, "getIdBits", pkg + ".Nodes$IdBits", loader);
446         testReturnType(nodesClass, "isIdBoolean", "java.lang.Boolean", loader);
447         testReturnType(nodesClass, "getIdDecimal64", "java.math.BigDecimal", loader);
448         testReturnType(nodesClass, "isIdEmpty", "java.lang.Boolean", loader);
449         testReturnType(nodesClass, "getIdEnumeration", pkg + ".Nodes$IdEnumeration", loader);
450         testReturnTypeIdentityref(nodesClass, "getIdIdentityref", pkg + ".Alg");
451         testReturnTypeInstanceIdentitifer(loader, nodesClass, "getIdInstanceIdentifier");
452         testReturnType(nodesClass, "getId8", "java.lang.Byte", loader);
453         testReturnType(nodesClass, "getId16", "java.lang.Short", loader);
454         testReturnType(nodesClass, "getId32", "java.lang.Integer", loader);
455         testReturnType(nodesClass, "getId64", "java.lang.Long", loader);
456         testReturnType(nodesClass, "getIdLeafref", "java.lang.Long", loader);
457         testReturnType(nodesClass, "getIdString", "java.lang.String", loader);
458         testReturnType(nodesClass, "getIdU8", "java.lang.Short", loader);
459         testReturnType(nodesClass, "getIdU16", "java.lang.Integer", loader);
460         testReturnType(nodesClass, "getIdU32", "java.lang.Long", loader);
461         testReturnType(nodesClass, "getIdU64", "java.math.BigInteger", loader);
462         testReturnType(nodesClass, "getIdUnion", pkg + ".Nodes$IdUnion", loader);
463
464         cleanUp(sourcesOutputDir, compiledOutputDir);
465     }
466
467     @Test
468     public void testGenerationContextReferenceExtension() throws Exception {
469         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "context-reference");
470         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
471         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "context-reference");
472         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
473
474         final List<File> sourceFiles = getSourceFiles("/compilation/context-reference");
475         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
476         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
477         final List<Type> types = bindingGenerator.generateTypes(context);
478         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
479         generator.generateToFile(sourcesOutputDir);
480
481         // Test if all sources are generated
482         File fooParent = new File(sourcesOutputDir, NS_FOO);
483         assertEquals(3, fooParent.listFiles().length);
484         assertTrue(new File(fooParent, "FooData.java").exists());
485         assertTrue(new File(fooParent, "Nodes.java").exists());
486         assertTrue(new File(fooParent, "NodesBuilder.java").exists());
487
488         File barParent = new File(sourcesOutputDir, NS_BAR);
489         assertEquals(1, barParent.listFiles().length);
490         assertTrue(new File(barParent, "IdentityClass.java").exists());
491
492         // Test if sources are compilable
493         testCompilation(sourcesOutputDir, compiledOutputDir);
494
495         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
496         Class<?> nodesClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.Nodes", true, loader);
497         Class<?> identityClass = Class
498                 .forName(BASE_PKG + ".urn.opendaylight.bar.rev131008.IdentityClass", true, loader);
499
500         // test identity
501         try {
502             identityClass.getConstructor();
503             Class<?> baseIdentity = Class.forName("org.opendaylight.yangtools.yang.binding.BaseIdentity", true, loader);
504             assertEquals(baseIdentity, identityClass.getSuperclass());
505         } catch (NoSuchMethodException e) {
506             throw new AssertionError("IdentityClass must have no-arg constructor");
507         }
508
509         // Test annotation
510         try {
511             Method getId = nodesClass.getMethod("getId");
512             Annotation[] annotations = getId.getAnnotations();
513             assertEquals(1, annotations.length);
514             Annotation routingContext = annotations[0];
515             assertEquals(RoutingContext.class, routingContext.annotationType());
516         } catch (NoSuchMethodException e) {
517             throw new AssertionError("Method getId() not found");
518         }
519
520         cleanUp(sourcesOutputDir, compiledOutputDir);
521     }
522
523     @Test
524     public void testAugmentToUsesInAugment() throws Exception {
525         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-uses-to-augment");
526         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
527         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-uses-to-augment");
528         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
529
530         final List<File> sourceFiles = getSourceFiles("/compilation/augment-uses-to-augment");
531         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
532         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
533         final List<Type> types = bindingGenerator.generateTypes(context);
534         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
535         generator.generateToFile(sourcesOutputDir);
536
537         // Test if all sources are generated
538         File fooParent = new File(sourcesOutputDir, NS_FOO);
539         assertEquals(4, fooParent.listFiles().length);
540         assertTrue(new File(fooParent, "IgpLinkAttributes.java").exists());
541         assertTrue(new File(fooParent, "Link1.java").exists());
542         assertTrue(new File(fooParent, "Link1Builder.java").exists());
543
544         File bazParent = new File(sourcesOutputDir, NS_BAZ);
545         assertEquals(4, bazParent.listFiles().length);
546         assertTrue(new File(bazParent, "IgpLinkAttributes1.java").exists());
547         assertTrue(new File(bazParent, "IgpLinkAttributes1Builder.java").exists());
548         assertTrue(new File(bazParent, "LinkAttributes.java").exists());
549
550         // Test if sources are compilable
551         testCompilation(sourcesOutputDir, compiledOutputDir);
552     }
553
554     @Test
555     public void compilationTest() throws Exception {
556         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
557         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
558         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "yang");
559         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
560
561         final List<File> sourceFiles = getSourceFiles("/yang");
562         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
563         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
564         final List<Type> types = bindingGenerator.generateTypes(context);
565         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
566         generator.generateToFile(sourcesOutputDir);
567
568         // Test if sources are compilable
569         testCompilation(sourcesOutputDir, compiledOutputDir);
570
571         cleanUp(sourcesOutputDir, compiledOutputDir);
572     }
573
574     /**
575      * Test if source code is compilable.
576      *
577      * @param sourcesOutputDir
578      *            directory containing source files
579      * @param compiledOutputDir
580      *            compiler output directory
581      */
582     private void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
583         List<File> filesList = getJavaFiles(sourcesOutputDir);
584         Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
585         Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
586         boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
587         assertTrue(compiled);
588     }
589
590     private void testImplementIfc(Class<?> classToTest, String ifc, ClassLoader loader) throws ClassNotFoundException {
591         Class<?>[] interfaces = classToTest.getInterfaces();
592         List<Class<?>> ifcsList = Arrays.asList(interfaces);
593         Class<?> ifcClass = Class.forName(ifc, true, loader);
594         testImplementIfc(classToTest, ifcClass);
595     }
596
597     private void testImplementIfc(Class<?> classToTest, Class<?> ifcClass) throws ClassNotFoundException {
598         Class<?>[] interfaces = classToTest.getInterfaces();
599         List<Class<?>> ifcsList = Arrays.asList(interfaces);
600         if (!ifcsList.contains(ifcClass)) {
601             throw new AssertionError(classToTest + " should implement " + ifcClass);
602         }
603     }
604
605     private void testReturnType(Class<?> clazz, String methodName, Class<?> returnType) throws Exception {
606         Method method;
607         try {
608             method = clazz.getMethod(methodName);
609             assertEquals(returnType, method.getReturnType());
610         } catch (NoSuchMethodException e) {
611             throw new AssertionError("Method '" + methodName + "' not found");
612         }
613     }
614
615     private void testReturnType(Class<?> clazz, String methodName, String returnTypeStr, ClassLoader loader)
616             throws Exception {
617         Class<?> returnType;
618         try {
619             returnType = Class.forName(returnTypeStr, true, loader);
620             testReturnType(clazz, methodName, returnType);
621         } catch (ClassNotFoundException e) {
622             throw new AssertionError("Return type of method '" + methodName + "' not found");
623         }
624     }
625
626     private void testReturnTypeIdentityref(Class<?> clazz, String methodName, String returnTypeStr) throws Exception {
627         Method method;
628         java.lang.reflect.Type returnType;
629         try {
630             method = clazz.getMethod(methodName);
631             assertEquals(java.lang.Class.class, method.getReturnType());
632             returnType = method.getGenericReturnType();
633             assertTrue(returnType instanceof ParameterizedType);
634             ParameterizedType pt = (ParameterizedType) returnType;
635             java.lang.reflect.Type[] parameters = pt.getActualTypeArguments();
636             assertEquals(1, parameters.length);
637             java.lang.reflect.Type parameter = parameters[0];
638             assertTrue(parameter instanceof WildcardType);
639             WildcardType wildcardType = (WildcardType) parameter;
640             assertEquals("? extends " + returnTypeStr, wildcardType.toString());
641         } catch (NoSuchMethodException e) {
642             throw new AssertionError("Method '" + methodName + "' not found");
643         }
644     }
645
646     private void testReturnTypeInstanceIdentitifer(ClassLoader loader, Class<?> clazz, String methodName)
647             throws Exception {
648         Method method;
649         Class<?> rawReturnType;
650         java.lang.reflect.Type returnType;
651         try {
652             method = clazz.getMethod(methodName);
653             rawReturnType = Class.forName("org.opendaylight.yangtools.yang.binding.InstanceIdentifier", true, loader);
654             assertEquals(rawReturnType, method.getReturnType());
655             returnType = method.getGenericReturnType();
656             assertTrue(returnType instanceof ParameterizedType);
657             ParameterizedType pt = (ParameterizedType) returnType;
658             java.lang.reflect.Type[] parameters = pt.getActualTypeArguments();
659             assertEquals(1, parameters.length);
660             java.lang.reflect.Type parameter = parameters[0];
661             assertTrue(parameter instanceof WildcardType);
662             WildcardType wildcardType = (WildcardType) parameter;
663             assertEquals("?", wildcardType.toString());
664         } catch (NoSuchMethodException e) {
665             throw new AssertionError("Method '" + methodName + "' not found");
666         }
667     }
668
669     private List<File> getSourceFiles(String path) throws FileNotFoundException {
670         final String resPath = getClass().getResource(path).getPath();
671         final File sourcesDir = new File(resPath);
672         if (sourcesDir.exists()) {
673             final List<File> sourceFiles = new ArrayList<>();
674             final File[] fileArray = sourcesDir.listFiles();
675             if (fileArray == null) {
676                 throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
677             }
678             sourceFiles.addAll(Arrays.asList(fileArray));
679             return sourceFiles;
680         } else {
681             throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
682         }
683     }
684
685     private static void deleteTestDir(File file) {
686         if (file.isDirectory()) {
687             File[] filesToDelete = file.listFiles();
688             if (filesToDelete != null) {
689                 for (File f : filesToDelete) {
690                     deleteTestDir(f);
691                 }
692             }
693         }
694         if (!file.delete()) {
695             throw new RuntimeException("Failed to clean up after test");
696         }
697     }
698
699     /**
700      * Search recursively given directory for *.java files.
701      *
702      * @param directory
703      *            directory to search
704      * @return List of java files found
705      */
706     private List<File> getJavaFiles(File directory) {
707         List<File> result = new ArrayList<>();
708         File[] filesToRead = directory.listFiles();
709         if (filesToRead != null) {
710             for (File file : filesToRead) {
711                 if (file.isDirectory()) {
712                     result.addAll(getJavaFiles(file));
713                 } else {
714                     String absPath = file.getAbsolutePath();
715                     if (absPath.endsWith(".java")) {
716                         result.add(file);
717                     }
718                 }
719             }
720         }
721         return result;
722     }
723 }