Added export of augmentation schemas to Binding Context
[yangtools.git] / code-generator / binding-java-api-generator / src / test / java / org / opendaylight / yangtools / sal / java / api / generator / test / CompilationTestUtils.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.*;
11
12 import java.io.File;
13 import java.io.FileNotFoundException;
14 import java.lang.reflect.Field;
15 import java.lang.reflect.Method;
16 import java.lang.reflect.ParameterizedType;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.List;
20
21 import javax.tools.JavaCompiler;
22 import javax.tools.JavaFileObject;
23 import javax.tools.StandardJavaFileManager;
24 import javax.tools.ToolProvider;
25
26 public class CompilationTestUtils {
27     public static final String FS = File.separator;
28     static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
29
30     static final String TEST_PATH = "target" + FS + "test";
31     static final File TEST_DIR = new File(TEST_PATH);
32
33     static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
34     static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
35     static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
36     static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
37
38     static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
39     static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
40     static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
41     static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
42     static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
43
44     /**
45      * Method to clean resources. It is manually called at the end of each test
46      * instead of marking it with @After annotation to prevent removing
47      * generated code if test fails.
48      */
49     static void cleanUp(File... resourceDirs) {
50         for (File resourceDir : resourceDirs) {
51             if (resourceDir.exists()) {
52                 deleteTestDir(resourceDir);
53             }
54         }
55     }
56
57     static Field assertContainsField(Class<?> clazz, String name, Class<?> type) {
58         try {
59             Field f = clazz.getDeclaredField(name);
60             assertEquals(type, f.getType());
61             return f;
62         } catch (NoSuchFieldException e) {
63             throw new AssertionError("Field " + name + " does not exists in class " + clazz.getSimpleName());
64         }
65     }
66
67     static void assertContainsConstructor(Class<?> clazz, Class<?>... args) {
68         try {
69             clazz.getDeclaredConstructor(args);
70         } catch (NoSuchMethodException e) {
71             throw new AssertionError("Constructor with args " + Arrays.toString(args) + " does not exists in class "
72                     + clazz.getSimpleName());
73         }
74     }
75
76     static void assertContainsMethod(Class<?> clazz, Class<?> returnType, String name, Class<?>... args) {
77         try {
78             Method m = clazz.getDeclaredMethod(name, args);
79             assertEquals(returnType, m.getReturnType());
80         } catch (NoSuchMethodException e) {
81             throw new AssertionError("Method " + name + " with args " + Arrays.toString(args)
82                     + " does not exists in class " + clazz.getSimpleName());
83         }
84     }
85
86     static void assertContainsMethod(Class<?> clazz, String returnTypeStr, String name, ClassLoader loader)
87             throws Exception {
88         Class<?> returnType;
89         try {
90             returnType = Class.forName(returnTypeStr, true, loader);
91             Method method = clazz.getMethod(name);
92             assertEquals(returnType, method.getReturnType());
93         } catch (ClassNotFoundException e) {
94             throw new AssertionError("Return type of method '" + name + "' not found");
95         }
96     }
97
98     /**
99      * Check for presence of hashCode, equals and toString methods.
100      *
101      * @param clazz
102      *            class to check
103      */
104     static void assertContainsDefaultMethods(Class<?> clazz) {
105         assertContainsMethod(clazz, Integer.TYPE, "hashCode");
106         assertContainsMethod(clazz, Boolean.TYPE, "equals", Object.class);
107         assertContainsMethod(clazz, String.class, "toString");
108     }
109
110     /**
111      * Check for presence of 'public static
112      * java.util.List<com.google.common.collect.Range<java.lang.Integer>>
113      * getLength()' method.
114      *
115      * @param clazz
116      *            class to check
117      */
118     static void assertContainsGetLength(Class<?> clazz) {
119         try {
120             Method m = clazz.getDeclaredMethod("getLength");
121             java.lang.reflect.Type returnType = m.getGenericReturnType();
122             assertTrue("Return type of getLength method must be ParameterizedType",
123                     returnType instanceof ParameterizedType);
124             ParameterizedType listType = (ParameterizedType) returnType;
125             assertEquals("interface java.util.List", listType.getRawType().toString());
126
127             java.lang.reflect.Type[] args = listType.getActualTypeArguments();
128             assertEquals(1, args.length);
129             java.lang.reflect.Type range = args[0];
130             assertTrue(range instanceof ParameterizedType);
131             ParameterizedType pRange = (ParameterizedType) range;
132             assertEquals("class com.google.common.collect.Range", pRange.getRawType().toString());
133
134             args = pRange.getActualTypeArguments();
135             assertEquals(1, args.length);
136             java.lang.reflect.Type integer = args[0];
137             assertEquals("class java.lang.Integer", integer.toString());
138         } catch (NoSuchMethodException e) {
139             throw new AssertionError("Method getLength does not exists in class " + clazz.getSimpleName());
140         }
141     }
142
143     /**
144      * Test if generated source implements interface.
145      *
146      * @param classToTest
147      *            source to test
148      * @param ifcClass
149      *            expected interface type
150      */
151     static void testImplementsIfc(Class<?> classToTest, Class<?> ifcClass) {
152         Class<?>[] interfaces = classToTest.getInterfaces();
153         List<Class<?>> ifcsList = Arrays.asList(interfaces);
154         if (!ifcsList.contains(ifcClass)) {
155             throw new AssertionError(classToTest + " should implement " + ifcClass);
156         }
157     }
158
159     /**
160      * Test if interface generated from augment extends Augmentation interface
161      * with correct generic type.
162      *
163      * @param classToTest
164      *            interface generated from augment
165      * @param genericType
166      *            fully qualified name of expected parameter type
167      */
168     static void testAugmentation(Class<?> classToTest, String genericType) {
169         final String ifcToImplement = "interface org.opendaylight.yangtools.yang.binding.Augmentation";
170         testImplementParameterizedIfc(classToTest, ifcToImplement, genericType);
171     }
172
173     static void testImplementParameterizedIfc(Class<?> classToTest, String ifcToImplement, String genericType) {
174         ParameterizedType augmentation = null;
175         for (java.lang.reflect.Type ifc : classToTest.getGenericInterfaces()) {
176             if (ifc instanceof ParameterizedType) {
177                 ParameterizedType pt = (ParameterizedType) ifc;
178                 if (ifcToImplement.equals(pt.getRawType().toString())) {
179                     augmentation = pt;
180                 }
181             }
182         }
183         assertNotNull(augmentation);
184
185         java.lang.reflect.Type[] typeArguments = augmentation.getActualTypeArguments();
186         assertEquals(1, typeArguments.length);
187         assertEquals("interface " + genericType, typeArguments[0].toString());
188     }
189
190     /**
191      * Test if source code is compilable.
192      *
193      * @param sourcesOutputDir
194      *            directory containing source files
195      * @param compiledOutputDir
196      *            compiler output directory
197      */
198     static void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
199         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
200         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
201         List<File> filesList = getJavaFiles(sourcesOutputDir);
202         Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
203         Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
204         boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
205         assertTrue(compiled);
206     }
207
208     static void testFilesCount(File dir, int count) {
209         File[] dirContent = dir.listFiles();
210         if (dirContent == null) {
211             throw new AssertionError("File " + dir + " doesn't exists or it's not a directory");
212         } else {
213             assertEquals("Unexpected count of generated files", count, dirContent.length);
214         }
215     }
216
217     /**
218      * Search recursively given directory for *.java files.
219      *
220      * @param directory
221      *            directory to search
222      * @return List of java files found
223      */
224     private static List<File> getJavaFiles(File directory) {
225         List<File> result = new ArrayList<>();
226         File[] filesToRead = directory.listFiles();
227         if (filesToRead != null) {
228             for (File file : filesToRead) {
229                 if (file.isDirectory()) {
230                     result.addAll(getJavaFiles(file));
231                 } else {
232                     String absPath = file.getAbsolutePath();
233                     if (absPath.endsWith(".java")) {
234                         result.add(file);
235                     }
236                 }
237             }
238         }
239         return result;
240     }
241
242     static List<File> getSourceFiles(String path) throws FileNotFoundException {
243         final String resPath = BaseCompilationTest.class.getResource(path).getPath();
244         final File sourcesDir = new File(resPath);
245         if (sourcesDir.exists()) {
246             final List<File> sourceFiles = new ArrayList<>();
247             final File[] fileArray = sourcesDir.listFiles();
248             if (fileArray == null) {
249                 throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
250             }
251             sourceFiles.addAll(Arrays.asList(fileArray));
252             return sourceFiles;
253         } else {
254             throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
255         }
256     }
257
258     static void deleteTestDir(File file) {
259         if (file.isDirectory()) {
260             File[] filesToDelete = file.listFiles();
261             if (filesToDelete != null) {
262                 for (File f : filesToDelete) {
263                     deleteTestDir(f);
264                 }
265             }
266         }
267         if (!file.delete()) {
268             throw new RuntimeException("Failed to clean up after test");
269         }
270     }
271
272 }