Merge "public modifier added"
[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.assertTrue;
11
12 import java.io.File;
13 import java.net.URL;
14 import java.net.URLClassLoader;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20
21 import javax.tools.JavaCompiler;
22 import javax.tools.JavaFileObject;
23 import javax.tools.StandardJavaFileManager;
24 import javax.tools.ToolProvider;
25
26 import org.junit.Before;
27 import org.junit.BeforeClass;
28 import org.junit.Test;
29 import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
30 import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
31 import org.opendaylight.yangtools.sal.binding.model.api.Type;
32 import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
33 import org.opendaylight.yangtools.yang.model.api.Module;
34 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
35 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
36
37 /**
38  * Test correct code generation.
39  * 
40  */
41 public class CompilationTest {
42     private static final String FS = File.separator;
43     private static final String TEST_PATH = "target" + FS + "test";
44     private static final File TEST_DIR = new File(TEST_PATH);
45
46     private static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
47     private static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
48     private static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
49     private static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
50
51     private YangParserImpl parser;
52     private BindingGenerator bindingGenerator;
53
54     @BeforeClass
55     public static void createTestDirs() {
56         if (TEST_DIR.exists()) {
57             deleteTestDir(TEST_DIR);
58         }
59         assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
60         assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
61     }
62
63     @Before
64     public void init() {
65         parser = new YangParserImpl();
66         bindingGenerator = new BindingGeneratorImpl();
67     }
68
69     /**
70      * Method to clean resources. It is manually called at the end of each test
71      * instead of marking it with @After annotation to prevent removing
72      * generated code if test fails.
73      */
74     public void cleanUp(File... resourceDirs) {
75         for (File resourceDir : resourceDirs) {
76             if (resourceDir.exists()) {
77                 deleteTestDir(resourceDir);
78             }
79         }
80     }
81
82     @Test
83     public void testListGeneration() throws Exception {
84         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "list-gen");
85         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
86         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "list-gen");
87         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
88
89         final List<File> sourceFiles = getSourceFiles("/compilation/list-gen");
90         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
91         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
92         final List<Type> types = bindingGenerator.generateTypes(context);
93         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
94         generator.generateToFile(sourcesOutputDir);
95
96         File parent = new File(sourcesOutputDir, "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1"
97                 + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008");
98         File linksKeyFile = new File(parent, "LinksKey.java");
99         assertTrue(new File(parent, "KeyArgs.java").exists());
100         assertTrue(new File(parent, "Links.java").exists());
101         assertTrue(new File(parent, "LinksBuilder.java").exists());
102         assertTrue(linksKeyFile.exists());
103         assertTrue(new File(parent, "TestData.java").exists());
104         assertTrue(new File(parent, "links" + FS + "Level.java").exists());
105         assertTrue(new File(parent, "links" + FS + "LinkGroup.java").exists());
106         assertTrue(new File(parent, "links" + FS + "Node.java").exists());
107         assertTrue(new File(parent, "links" + FS + "NodeBuilder.java").exists());
108         assertTrue(new File(parent, "links" + FS + "NodeList.java").exists());
109         assertTrue(new File(parent, "links" + FS + "NodeListBuilder.java").exists());
110         assertTrue(linksKeyFile.exists());
111
112         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
113         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
114
115         List<File> filesList = getJavaFiles(sourcesOutputDir);
116         Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
117         Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
118         boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
119         assertTrue(compiled);
120
121         ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
122         Class<?> linksKeyClass = Class.forName("org.opendaylight.yang.gen.v1.urn.opendaylight.test.rev131008.LinksKey",
123                 true, loader);
124
125         // test list key constructor arguments ordering
126         try {
127             linksKeyClass.getConstructor(Byte.class, String.class, Integer.class);
128         } catch (NoSuchMethodException e) {
129             throw new AssertionError("Parameters of list key constructor are not properly ordered");
130         }
131
132         cleanUp(sourcesOutputDir, compiledOutputDir);
133     }
134
135     @Test
136     public void testAugmentUnderUsesGeneration() throws Exception {
137         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-under-uses");
138         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
139         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-under-uses");
140         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
141
142         final List<File> sourceFiles = getSourceFiles("/compilation/augment-under-uses");
143         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
144         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
145         final List<Type> types = bindingGenerator.generateTypes(context);
146         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
147         generator.generateToFile(sourcesOutputDir);
148
149         File parent = new File(sourcesOutputDir + FS + "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS
150                 + "v1" + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008");
151         assertTrue(new File(parent, "Object.java").exists());
152         assertTrue(new File(parent, "OpenObject.java").exists());
153         assertTrue(new File(parent, "object" + FS + "Nodes.java").exists());
154         assertTrue(new File(parent, "object" + FS + "NodesBuilder.java").exists());
155         assertTrue(new File(parent, "open" + FS + "object" + FS + "Nodes1.java").exists());
156         assertTrue(new File(parent, "open" + FS + "object" + FS + "Nodes1Builder.java").exists());
157         assertTrue(new File(parent, "open" + FS + "object" + FS + "nodes" + FS + "Links.java").exists());
158         assertTrue(new File(parent, "open" + FS + "object" + FS + "nodes" + FS + "LinksBuilder.java").exists());
159
160         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
161         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
162
163         List<File> filesList = getJavaFiles(sourcesOutputDir);
164         Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
165         Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
166         boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
167         assertTrue(compiled);
168
169         cleanUp(sourcesOutputDir, compiledOutputDir);
170     }
171
172     @Test
173     public void compilationTest() throws Exception {
174         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
175         assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
176         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "yang");
177         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
178
179         final List<File> sourceFiles = getSourceFiles("/yang");
180         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
181         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
182         final List<Type> types = bindingGenerator.generateTypes(context);
183         final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
184         generator.generateToFile(sourcesOutputDir);
185
186         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
187         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
188
189         List<File> filesList = getJavaFiles(sourcesOutputDir);
190         Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
191         Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
192         boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
193         assertTrue(compiled);
194     }
195
196     private List<File> getSourceFiles(String path) {
197         final String resPath = getClass().getResource(path).getPath();
198         final File sourcesDir = new File(resPath);
199         final List<File> sourceFiles = new ArrayList<>();
200         final File[] fileArray = sourcesDir.listFiles();
201         sourceFiles.addAll(Arrays.asList(fileArray));
202         return sourceFiles;
203     }
204
205     private static void deleteTestDir(File file) {
206         if (file.isDirectory()) {
207             for (File f : file.listFiles()) {
208                 deleteTestDir(f);
209             }
210         }
211         if (!file.delete()) {
212             throw new RuntimeException("Failed to clean up after test");
213         }
214     }
215
216     /**
217      * Search recursively given directory for *.java files.
218      * 
219      * @param directory
220      *            directory to search
221      * @return List of java files found
222      */
223     private List<File> getJavaFiles(File directory) {
224         List<File> result = new ArrayList<File>();
225         for (File file : directory.listFiles()) {
226             if (file.isDirectory()) {
227                 result.addAll(getJavaFiles(file));
228             } else {
229                 String absPath = file.getAbsolutePath();
230                 if (absPath.endsWith(".java")) {
231                     result.add(file);
232                 }
233             }
234         }
235         return result;
236     }
237 }