2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.mdsal.binding.java.api.generator.test;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
16 import java.io.FileNotFoundException;
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.Field;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Modifier;
22 import java.lang.reflect.ParameterizedType;
24 import java.net.URISyntaxException;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import javax.tools.Diagnostic;
29 import javax.tools.JavaCompiler;
30 import javax.tools.JavaFileObject;
31 import javax.tools.StandardJavaFileManager;
32 import javax.tools.ToolProvider;
34 public class CompilationTestUtils {
35 public static final String FS = File.separator;
36 static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
38 static final String TEST_PATH = "target" + FS + "test";
39 static final File TEST_DIR = new File(TEST_PATH);
41 static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
42 static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
43 static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
44 static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
46 static final String AUGMENTATION = "interface org.opendaylight.yangtools.yang.binding.Augmentation";
47 static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
48 static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
49 static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
50 static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
51 static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
52 static final String NS_BUG5882 = BASE_PATH + FS + "urn" + FS + "yang" + FS + "foo" + FS + "rev160102";
55 * Method to clean resources. It is manually called at the end of each test
56 * instead of marking it with @After annotation to prevent removing
57 * generated code if test fails.
59 static void cleanUp(final File... resourceDirs) {
60 for (File resourceDir : resourceDirs) {
61 if (resourceDir.exists()) {
62 deleteTestDir(resourceDir);
68 * Asserts that class contains field with fiven name and type.
76 * @return field with given name if present in class
78 static Field assertContainsField(final Class<?> clazz, final String name, final Class<?> type) {
80 Field f = clazz.getDeclaredField(name);
81 assertEquals(type, f.getType());
83 } catch (NoSuchFieldException e) {
84 throw new AssertionError("Field " + name + " does not exist in class " + clazz.getSimpleName());
89 * Asserts that class contains field with given name and value. Method tries
90 * to create new instance of class and get value of field. If class
91 * constructor contains any arguments, class is instantiated with null
99 * return type of field
100 * @param expectedValue
101 * expected value of field
102 * @param constructorArgs
103 * constructor arguments of class to test
105 static void assertContainsFieldWithValue(final Class<?> clazz, final String name, final Class<?> returnType, final Object expectedValue,
106 final Class<?>... constructorArgs) {
107 Object[] initargs = null;
108 if (constructorArgs != null && constructorArgs.length > 0) {
109 initargs = new Object[constructorArgs.length];
110 for (int i = 0; i < constructorArgs.length; i++) {
114 assertContainsFieldWithValue(clazz, name, returnType, expectedValue, constructorArgs, initargs);
118 * Asserts that class contains field with given name, return type and value.
125 * return type of field
126 * @param expectedValue
127 * expected value of field
128 * @param constructorArgs
129 * array of constructor arguments classes
131 * array of constructor values
133 static void assertContainsFieldWithValue(final Class<?> clazz, final String name, final Class<?> returnType, final Object expectedValue,
134 final Class<?>[] constructorArgs, final Object... initargs) {
135 Field f = assertContainsField(clazz, name, returnType);
136 f.setAccessible(true);
139 if ((f.getModifiers() & Modifier.STATIC) == 0) {
141 Constructor<?> c = clazz.getDeclaredConstructor(constructorArgs);
142 obj = c.newInstance(initargs);
143 } catch (Exception e) {
144 throw new AssertionError("Failed to instantiate object for " + clazz, e);
151 assertEquals(expectedValue, f.get(obj));
152 } catch (IllegalArgumentException | IllegalAccessException e) {
153 throw new AssertionError("Failed to get field " + name + " of class " + clazz, e);
158 * Asserts that class contains constructor with parameter types.
163 * array of argument classes
165 static Constructor<?> assertContainsConstructor(final Class<?> clazz, final Class<?>... args) {
167 return clazz.getDeclaredConstructor(args);
168 } catch (NoSuchMethodException e) {
169 throw new AssertionError("Constructor with args " + Arrays.toString(args) + " does not exists in class "
170 + clazz.getSimpleName());
175 * Asserts that class contains method with given name, return type and
185 * array of parameter type classes
186 * @return method with given name, return type and parameter types
188 static Method assertContainsMethod(final Class<?> clazz, final Class<?> returnType, final String name, final Class<?>... args) {
190 Method m = clazz.getDeclaredMethod(name, args);
191 assertEquals(returnType, m.getReturnType());
193 } catch (NoSuchMethodException e) {
194 throw new AssertionError("Method " + name + " with args " + Arrays.toString(args)
195 + " does not exists in class " + clazz.getSimpleName());
200 * Asserts that class contains method with given name and return type.
204 * @param returnTypeStr
205 * name of method return type
209 * current class loader
211 static void assertContainsMethod(final Class<?> clazz, final String returnTypeStr, final String name, final ClassLoader loader) {
214 returnType = Class.forName(returnTypeStr, true, loader);
215 Method method = clazz.getMethod(name);
216 assertEquals(returnType, method.getReturnType());
217 } catch (ClassNotFoundException e) {
218 throw new AssertionError("Return type of method '" + name + "' not found");
219 } catch (NoSuchMethodException e) {
220 throw new AssertionError("Method " + name + " does not exists in class " + clazz.getSimpleName());
225 * Asserts that class contains hashCode, equals and toString methods.
230 static void assertContainsDefaultMethods(final Class<?> clazz) {
231 assertContainsMethod(clazz, Integer.TYPE, "hashCode");
232 assertContainsMethod(clazz, Boolean.TYPE, "equals", Object.class);
233 assertContainsMethod(clazz, String.class, "toString");
237 * Asserts that constructor contains check for illegal argument.
240 * constructor to invoke
242 * expected error message
244 * constructor arguments
247 static void assertContainsRestrictionCheck(final Constructor<?> constructor, final String errorMsg, final Object... args)
250 constructor.newInstance(args);
251 fail("constructor invocation should fail");
252 } catch (InvocationTargetException e) {
253 Throwable cause = e.getCause();
254 assertTrue(cause instanceof IllegalArgumentException);
255 assertEquals(errorMsg, cause.getMessage());
260 * Asserts that method contains check for illegal argument.
263 * object to test (can be null, if method is static)
267 * expected error message
269 * constructor arguments
272 static void assertContainsRestrictionCheck(final Object obj, final Method method, final String errorMsg, final Object... args)
275 method.invoke(obj, args);
276 fail("method invocation should fail");
277 } catch (InvocationTargetException e) {
278 Throwable cause = e.getCause();
279 assertTrue(cause instanceof IllegalArgumentException);
280 assertEquals(errorMsg, cause.getMessage());
285 * Asserts that class implements given interface.
292 static void assertImplementsIfc(final Class<?> clazz, final Class<?> ifc) {
293 Class<?>[] interfaces = clazz.getInterfaces();
294 List<Class<?>> ifcsList = Arrays.asList(interfaces);
295 if (!ifcsList.contains(ifc)) {
296 throw new AssertionError(clazz + " should implement " + ifc);
301 * Test if interface generated from augment extends Augmentation interface
302 * with correct generic type.
305 * interface generated from augment
306 * @param genericTypeName
307 * fully qualified name of expected parameter type
309 static void testAugmentation(final Class<?> clazz, final String genericTypeName) {
310 assertImplementsParameterizedIfc(clazz, AUGMENTATION, genericTypeName);
314 * Asserts that class implements interface with given name and generic type
321 * @param genericTypeName
322 * name of generic type
324 static void assertImplementsParameterizedIfc(final Class<?> clazz, final String ifcName, final String genericTypeName) {
325 ParameterizedType ifcType = null;
326 for (java.lang.reflect.Type ifc : clazz.getGenericInterfaces()) {
327 if (ifc instanceof ParameterizedType) {
328 ParameterizedType pt = (ParameterizedType) ifc;
329 if (ifcName.equals(pt.getRawType().toString())) {
334 assertNotNull(ifcType);
336 java.lang.reflect.Type[] typeArguments = ifcType.getActualTypeArguments();
337 assertEquals(1, typeArguments.length);
338 assertEquals("interface " + genericTypeName, typeArguments[0].toString());
342 * Test if source code is compilable.
344 * @param sourcesOutputDir
345 * directory containing source files
346 * @param compiledOutputDir
347 * compiler output directory
349 static void testCompilation(final File sourcesOutputDir, final File compiledOutputDir) {
350 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
351 StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
352 List<File> filesList = getJavaFiles(sourcesOutputDir);
353 Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
354 Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
356 List<Diagnostic<?>> diags = new ArrayList<>();
357 boolean compiled = compiler.getTask(null, null, diags::add, options, null, compilationUnits).call();
359 fail("Compilation failed with " + diags);
364 * Asserts that directory contains exactly given count of files.
369 * expected count of files in directory
371 static void assertFilesCount(final File dir, final int count) {
372 File[] dirContent = dir.listFiles();
373 if (dirContent == null) {
374 throw new AssertionError("File " + dir + " doesn't exists or it's not a directory");
376 assertEquals("Unexpected count of generated files", count, dirContent.length);
381 * Search recursively given directory for *.java files.
384 * directory to search
385 * @return List of java files found
387 private static List<File> getJavaFiles(final File directory) {
388 List<File> result = new ArrayList<>();
389 File[] filesToRead = directory.listFiles();
390 if (filesToRead != null) {
391 for (File file : filesToRead) {
392 if (file.isDirectory()) {
393 result.addAll(getJavaFiles(file));
395 String absPath = file.getAbsolutePath();
396 if (absPath.endsWith(".java")) {
405 static List<File> getSourceFiles(final String path) throws FileNotFoundException, URISyntaxException {
406 final URI resPath = BaseCompilationTest.class.getResource(path).toURI();
407 final File sourcesDir = new File(resPath);
408 if (!sourcesDir.exists()) {
409 throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
412 final List<File> sourceFiles = new ArrayList<>();
413 final File[] fileArray = sourcesDir.listFiles();
414 if (fileArray == null) {
415 throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
417 sourceFiles.addAll(Arrays.asList(fileArray));
421 static void deleteTestDir(final File file) {
422 if (file.isDirectory()) {
423 File[] filesToDelete = file.listFiles();
424 if (filesToDelete != null) {
425 for (File f : filesToDelete) {
430 if (!file.delete()) {
431 throw new RuntimeException("Failed to clean up after test");