Added constructors to builder classes based on implemented interfaces from uses nodes. 47/2147/1
authorMartin Vitez <mvitez@cisco.com>
Thu, 24 Oct 2013 16:22:19 +0000 (18:22 +0200)
committerMartin Vitez <mvitez@cisco.com>
Thu, 24 Oct 2013 16:24:14 +0000 (18:24 +0200)
Added more tests.

Signed-off-by: Martin Vitez <mvitez@cisco.com>
12 files changed:
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BaseTemplate.xtend
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/BaseCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CascadeUsesCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/ClassCodeGeneratorTest.java
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java
code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/baz.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/foo.yang [new file with mode: 0644]
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserSimpleTest.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserTest.java

index 0972792625882ca67a25200cc67baaa589bb8dd2..4d28de3b1a49ada2140783a93133b18751797fce 100644 (file)
@@ -6,6 +6,7 @@ import java.util.Map
 import org.opendaylight.yangtools.sal.binding.model.api.Type
 import org.opendaylight.yangtools.binding.generator.util.Types
 import com.google.common.base.Splitter
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
 
 abstract class BaseTemplate {
     
@@ -33,7 +34,7 @@ abstract class BaseTemplate {
     '''
     «packageDefinition»
     «imports»
-    
+
     «_body»
     '''.toString
     }
@@ -45,15 +46,28 @@ abstract class BaseTemplate {
                 «ENDIF»
             «ENDFOR»
         «ENDIF»
-        
+
     '''
-    
+
     protected abstract def CharSequence body();
 
     // Helper patterns
-    
+
     final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
-    
+
+
+    final protected def propertyNameFromGetter(MethodSignature getter) {
+        var int prefix;
+        if (getter.name.startsWith("is")) {
+            prefix = 2
+        } else if (getter.name.startsWith("get")) {
+            prefix = 3
+        } else {
+            throw new IllegalArgumentException("Not a getter")
+        }
+        return getter.name.substring(prefix).toFirstLower;
+    }
+
     /**
      * Template method which generates the getter method for <code>field</code>
      * 
@@ -68,7 +82,7 @@ abstract class BaseTemplate {
         }
     '''
     }
-    
+
     final protected def getterMethodName(GeneratedProperty field) {
         val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
         return '''«prefix»«field.name.toFirstUpper»'''
index 68b36fe2cb12abd71a382e2ecda704b8141aa6be..94aa9788320dc8711e8e48111f0484b038bc70db 100644 (file)
@@ -203,6 +203,8 @@ class BuilderTemplate extends BaseTemplate {
 \r
             «generateFields(false)»\r
 \r
+            «generateBuilderConstructor(type)»\r
+\r
             «generateGetters(false)»\r
 \r
             «generateSetters»\r
@@ -212,7 +214,7 @@ class BuilderTemplate extends BaseTemplate {
             }\r
 \r
             private static final class «type.name»«IMPL» implements «type.name» {\r
-                \r
+\r
                 «implementedInterfaceGetter»\r
 \r
                 «generateFields(true)»\r
@@ -229,6 +231,35 @@ class BuilderTemplate extends BaseTemplate {
         }\r
     '''\r
 \r
+\r
+    def private generateBuilderConstructor(Type implementedIfc) '''\r
+        public «type.name»«BUILDER»() {\r
+        }\r
+\r
+        «IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»\r
+        «val ifc = implementedIfc as GeneratedType»\r
+        «FOR impl : ifc.implements»\r
+            «IF (impl instanceof GeneratedType) &&  !((impl as GeneratedType).methodDefinitions.empty)»\r
+                public «type.name»«BUILDER»(«impl.fullyQualifiedName» arg) {\r
+                    «printBuilderConstructorProperties(impl)»\r
+                }\r
+            «ENDIF»\r
+        «ENDFOR»\r
+        «ENDIF»\r
+    '''\r
+\r
+    def private printBuilderConstructorProperties(Type implementedIfc) '''\r
+        «IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»\r
+        «val ifc = implementedIfc as GeneratedType»\r
+        «FOR getter : ifc.methodDefinitions»\r
+            this._«getter.propertyNameFromGetter» = arg.«getter.name»();\r
+        «ENDFOR»\r
+        «FOR impl : ifc.implements»\r
+        «printBuilderConstructorProperties(impl)»\r
+        «ENDFOR»\r
+        «ENDIF»\r
+    '''\r
+\r
        /**\r
         * Template method which generates class attributes.\r
         * \r
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java
new file mode 100644 (file)
index 0000000..8ae4e31
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class AugmentToUsesInAugmentCompilationTest extends BaseCompilationTest {
+
+    @Test
+    public void testAugmentToUsesInAugment() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-uses-to-augment");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-uses-to-augment");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/augment-uses-to-augment");
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if all sources are generated
+        File fooParent = new File(sourcesOutputDir, NS_FOO);
+        assertEquals(4, fooParent.listFiles().length);
+        assertTrue(new File(fooParent, "IgpLinkAttributes.java").exists());
+        assertTrue(new File(fooParent, "Link1.java").exists());
+        assertTrue(new File(fooParent, "Link1Builder.java").exists());
+
+        File bazParent = new File(sourcesOutputDir, NS_BAZ);
+        assertEquals(4, bazParent.listFiles().length);
+        assertTrue(new File(bazParent, "IgpLinkAttributes1.java").exists());
+        assertTrue(new File(bazParent, "IgpLinkAttributes1Builder.java").exists());
+        assertTrue(new File(bazParent, "LinkAttributes.java").exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+
+        try {
+            Class<?> igpLinkAttributes1Class = Class.forName(BASE_PKG
+                    + ".urn.opendaylight.baz.rev131008.IgpLinkAttributes1", true, loader);
+            String augmentableNode = BASE_PKG + ".urn.opendaylight.foo.rev131008.igp.link.attributes.IgpLinkAttributes";
+            testAugmentation(igpLinkAttributes1Class, augmentableNode);
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError("IdentityClass must have no-arg constructor");
+        }
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/BaseCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/BaseCompilationTest.java
new file mode 100644 (file)
index 0000000..64ac2b4
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public abstract class BaseCompilationTest {
+    public static final String FS = File.separator;
+    protected static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
+
+    protected static final String TEST_PATH = "target" + FS + "test";
+    protected static final File TEST_DIR = new File(TEST_PATH);
+
+    protected static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
+    protected static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
+    protected static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
+    protected static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
+
+    protected static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
+    protected static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS
+            + "rev131008";
+    protected static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
+    protected static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
+    protected static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
+
+    protected YangParserImpl parser;
+    protected BindingGenerator bindingGenerator;
+
+    @BeforeClass
+    public static void createTestDirs() {
+        if (TEST_DIR.exists()) {
+            deleteTestDir(TEST_DIR);
+        }
+        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+        assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
+    }
+
+    @Before
+    public void init() {
+        parser = new YangParserImpl();
+        bindingGenerator = new BindingGeneratorImpl();
+    }
+
+    /**
+     * Method to clean resources. It is manually called at the end of each test
+     * instead of marking it with @After annotation to prevent removing
+     * generated code if test fails.
+     */
+    protected void cleanUp(File... resourceDirs) {
+        for (File resourceDir : resourceDirs) {
+            if (resourceDir.exists()) {
+                deleteTestDir(resourceDir);
+            }
+        }
+    }
+
+    protected static void testImplementIfc(Class<?> classToTest, Class<?> ifcClass) throws ClassNotFoundException {
+        Class<?>[] interfaces = classToTest.getInterfaces();
+        List<Class<?>> ifcsList = Arrays.asList(interfaces);
+        if (!ifcsList.contains(ifcClass)) {
+            throw new AssertionError(classToTest + " should implement " + ifcClass);
+        }
+    }
+
+    protected static void testAugmentation(Class<?> classToTest, String paramClass) {
+        final String augmentationIfc = "interface org.opendaylight.yangtools.yang.binding.Augmentation";
+        ParameterizedType augmentation = null;
+        for (java.lang.reflect.Type ifc : classToTest.getGenericInterfaces()) {
+            if (ifc instanceof ParameterizedType) {
+                ParameterizedType pt = (ParameterizedType) ifc;
+                if (augmentationIfc.equals(pt.getRawType().toString())) {
+                    augmentation = pt;
+                }
+            }
+        }
+        assertNotNull(augmentation);
+
+        java.lang.reflect.Type[] typeArguments = augmentation.getActualTypeArguments();
+        assertEquals(1, typeArguments.length);
+        assertEquals("interface " + paramClass, typeArguments[0].toString());
+    }
+
+    /**
+     * Test if source code is compilable.
+     * 
+     * @param sourcesOutputDir
+     *            directory containing source files
+     * @param compiledOutputDir
+     *            compiler output directory
+     */
+    protected static void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+        List<File> filesList = getJavaFiles(sourcesOutputDir);
+        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
+        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
+        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
+        assertTrue(compiled);
+    }
+
+    /**
+     * Search recursively given directory for *.java files.
+     * 
+     * @param directory
+     *            directory to search
+     * @return List of java files found
+     */
+    private static List<File> getJavaFiles(File directory) {
+        List<File> result = new ArrayList<>();
+        File[] filesToRead = directory.listFiles();
+        if (filesToRead != null) {
+            for (File file : filesToRead) {
+                if (file.isDirectory()) {
+                    result.addAll(getJavaFiles(file));
+                } else {
+                    String absPath = file.getAbsolutePath();
+                    if (absPath.endsWith(".java")) {
+                        result.add(file);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    protected static List<File> getSourceFiles(String path) throws FileNotFoundException {
+        final String resPath = BaseCompilationTest.class.getResource(path).getPath();
+        final File sourcesDir = new File(resPath);
+        if (sourcesDir.exists()) {
+            final List<File> sourceFiles = new ArrayList<>();
+            final File[] fileArray = sourcesDir.listFiles();
+            if (fileArray == null) {
+                throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
+            }
+            sourceFiles.addAll(Arrays.asList(fileArray));
+            return sourceFiles;
+        } else {
+            throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
+        }
+    }
+
+    private static void deleteTestDir(File file) {
+        if (file.isDirectory()) {
+            File[] filesToDelete = file.listFiles();
+            if (filesToDelete != null) {
+                for (File f : filesToDelete) {
+                    deleteTestDir(f);
+                }
+            }
+        }
+        if (!file.delete()) {
+            throw new RuntimeException("Failed to clean up after test");
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CascadeUsesCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CascadeUsesCompilationTest.java
new file mode 100644 (file)
index 0000000..aa6cc07
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class CascadeUsesCompilationTest extends BaseCompilationTest {
+
+    @Test
+    public void testCascadeUsesCompilation() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "cascade-uses");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "cascade-uses");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/cascade-uses");
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if all sources are generated from module foo
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        assertEquals(5, parent.listFiles().length);
+        File fooData = new File(parent, "FooData.java");
+        File foo_gr1 = new File(parent, "FooGr1.java");
+        File nodes = new File(parent, "Nodes.java");
+        File nodesBuilder = new File(parent, "NodesBuilder.java");
+        assertTrue(fooData.exists());
+        assertTrue(foo_gr1.exists());
+        assertTrue(nodes.exists());
+        assertTrue(nodesBuilder.exists());
+
+        // Test if all sources are generated from module bar
+        parent = new File(sourcesOutputDir, NS_BAR);
+        assertEquals(2, parent.listFiles().length);
+        File barGr1 = new File(parent, "BarGr1.java");
+        File barGr2 = new File(parent, "BarGr2.java");
+        assertTrue(barGr1.exists());
+        assertTrue(barGr2.exists());
+
+        // Test if all sources are generated from module baz
+        parent = new File(sourcesOutputDir, NS_BAZ);
+        assertEquals(1, parent.listFiles().length);
+        File bazGr1 = new File(parent, "BazGr1.java");
+        assertTrue(bazGr1.exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> nodesClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.Nodes", true,
+                loader);
+        Class<?> nodesBuilderClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.NodesBuilder", true,
+                loader);
+        Class<?> fooGr1Class = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.FooGr1", true, loader);
+        Class<?> barGr2Class = Class.forName(BASE_PKG + ".urn.opendaylight.bar.rev131008.BarGr2", true, loader);
+
+        // test generated interface from 'container nodes'
+        testImplementIfc(nodesClass, fooGr1Class);
+        testImplementIfc(nodesClass, barGr2Class);
+
+        // test generated builder for 'container nodes'
+        assertFalse(nodesBuilderClass.isInterface());
+        Constructor<?>[] nodesBuilderConstructors = nodesBuilderClass.getConstructors();
+        assertEquals(3, nodesBuilderConstructors.length);
+
+        // test generation of builder constructors from uses in 'container nodes'
+        Constructor<?> defaultConstructor = null;
+        Constructor<?> usesFooGr1 = null;
+        Constructor<?> usesBarGr2 = null;
+        for (Constructor<?> c : nodesBuilderConstructors) {
+            Class<?>[] params = c.getParameterTypes();
+            if (params.length == 0) {
+                defaultConstructor = c;
+            } else {
+                assertEquals(1, params.length);
+                if (params[0].equals(fooGr1Class)) {
+                    usesFooGr1 = c;
+                } else if (params[0].equals(barGr2Class)) {
+                    usesBarGr2 = c;
+                }
+            }
+        }
+        assertNotNull(defaultConstructor);
+        assertNotNull(usesFooGr1);
+        assertNotNull(usesBarGr2);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+}
index 60b732ae706b59f6890c8ce53262b0a20c5398ae..a62bb64156c3b328ead708e4bfb2ef516a4600a0 100644 (file)
@@ -1,3 +1,10 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
 package org.opendaylight.yangtools.sal.java.api.generator.test;\r
 \r
 import static org.junit.Assert.assertEquals;\r
index 59d4523affb5e4e93104a1f994350b16f8c5c70c..ce011d8935010bb1a3c33909e417abd795c17159 100644 (file)
@@ -11,92 +11,28 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.WildcardType;
 import java.net.URL;
 import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import javax.tools.JavaCompiler;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
-
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
-import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
 import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
 /**
  * Test correct code generation.
  *
  */
-public class CompilationTest {
-    private static final String FS = File.separator;
-    private static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
-    private static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
-    private static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
-    private static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
-    private static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
-
-    private static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
-
-    private static final String TEST_PATH = "target" + FS + "test";
-    private static final File TEST_DIR = new File(TEST_PATH);
-
-    private static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
-    private static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
-    private static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
-    private static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
-
-    private YangParserImpl parser;
-    private BindingGenerator bindingGenerator;
-    private JavaCompiler compiler;
-    private StandardJavaFileManager fileManager;
-
-    @BeforeClass
-    public static void createTestDirs() {
-        if (TEST_DIR.exists()) {
-            deleteTestDir(TEST_DIR);
-        }
-        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
-        assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
-    }
-
-    @Before
-    public void init() {
-        parser = new YangParserImpl();
-        bindingGenerator = new BindingGeneratorImpl();
-        compiler = ToolProvider.getSystemJavaCompiler();
-        fileManager = compiler.getStandardFileManager(null, null, null);
-    }
-
-    /**
-     * Method to clean resources. It is manually called at the end of each test
-     * instead of marking it with @After annotation to prevent removing
-     * generated code if test fails.
-     */
-    public void cleanUp(File... resourceDirs) {
-        for (File resourceDir : resourceDirs) {
-            if (resourceDir.exists()) {
-                deleteTestDir(resourceDir);
-            }
-        }
-    }
+public class CompilationTest extends BaseCompilationTest {
 
     @Test
     public void testListGeneration() throws Exception {
@@ -520,37 +456,6 @@ public class CompilationTest {
         cleanUp(sourcesOutputDir, compiledOutputDir);
     }
 
-    @Test
-    public void testAugmentToUsesInAugment() throws Exception {
-        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-uses-to-augment");
-        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
-        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-uses-to-augment");
-        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
-
-        final List<File> sourceFiles = getSourceFiles("/compilation/augment-uses-to-augment");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
-
-        // Test if all sources are generated
-        File fooParent = new File(sourcesOutputDir, NS_FOO);
-        assertEquals(4, fooParent.listFiles().length);
-        assertTrue(new File(fooParent, "IgpLinkAttributes.java").exists());
-        assertTrue(new File(fooParent, "Link1.java").exists());
-        assertTrue(new File(fooParent, "Link1Builder.java").exists());
-
-        File bazParent = new File(sourcesOutputDir, NS_BAZ);
-        assertEquals(4, bazParent.listFiles().length);
-        assertTrue(new File(bazParent, "IgpLinkAttributes1.java").exists());
-        assertTrue(new File(bazParent, "IgpLinkAttributes1Builder.java").exists());
-        assertTrue(new File(bazParent, "LinkAttributes.java").exists());
-
-        // Test if sources are compilable
-        testCompilation(sourcesOutputDir, compiledOutputDir);
-    }
-
     @Test
     public void compilationTest() throws Exception {
         final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
@@ -571,36 +476,6 @@ public class CompilationTest {
         cleanUp(sourcesOutputDir, compiledOutputDir);
     }
 
-    /**
-     * Test if source code is compilable.
-     *
-     * @param sourcesOutputDir
-     *            directory containing source files
-     * @param compiledOutputDir
-     *            compiler output directory
-     */
-    private void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
-        List<File> filesList = getJavaFiles(sourcesOutputDir);
-        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
-        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
-        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
-        assertTrue(compiled);
-    }
-
-    private void testImplementIfc(Class<?> classToTest, String ifc, ClassLoader loader) throws ClassNotFoundException {
-        Class<?>[] interfaces = classToTest.getInterfaces();
-        List<Class<?>> ifcsList = Arrays.asList(interfaces);
-        Class<?> ifcClass = Class.forName(ifc, true, loader);
-        testImplementIfc(classToTest, ifcClass);
-    }
-
-    private void testImplementIfc(Class<?> classToTest, Class<?> ifcClass) throws ClassNotFoundException {
-        Class<?>[] interfaces = classToTest.getInterfaces();
-        List<Class<?>> ifcsList = Arrays.asList(interfaces);
-        if (!ifcsList.contains(ifcClass)) {
-            throw new AssertionError(classToTest + " should implement " + ifcClass);
-        }
-    }
 
     private void testReturnType(Class<?> clazz, String methodName, Class<?> returnType) throws Exception {
         Method method;
@@ -666,58 +541,4 @@ public class CompilationTest {
         }
     }
 
-    private List<File> getSourceFiles(String path) throws FileNotFoundException {
-        final String resPath = getClass().getResource(path).getPath();
-        final File sourcesDir = new File(resPath);
-        if (sourcesDir.exists()) {
-            final List<File> sourceFiles = new ArrayList<>();
-            final File[] fileArray = sourcesDir.listFiles();
-            if (fileArray == null) {
-                throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
-            }
-            sourceFiles.addAll(Arrays.asList(fileArray));
-            return sourceFiles;
-        } else {
-            throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
-        }
-    }
-
-    private static void deleteTestDir(File file) {
-        if (file.isDirectory()) {
-            File[] filesToDelete = file.listFiles();
-            if (filesToDelete != null) {
-                for (File f : filesToDelete) {
-                    deleteTestDir(f);
-                }
-            }
-        }
-        if (!file.delete()) {
-            throw new RuntimeException("Failed to clean up after test");
-        }
-    }
-
-    /**
-     * Search recursively given directory for *.java files.
-     *
-     * @param directory
-     *            directory to search
-     * @return List of java files found
-     */
-    private List<File> getJavaFiles(File directory) {
-        List<File> result = new ArrayList<>();
-        File[] filesToRead = directory.listFiles();
-        if (filesToRead != null) {
-            for (File file : filesToRead) {
-                if (file.isDirectory()) {
-                    result.addAll(getJavaFiles(file));
-                } else {
-                    String absPath = file.getAbsolutePath();
-                    if (absPath.endsWith(".java")) {
-                        result.add(file);
-                    }
-                }
-            }
-        }
-        return result;
-    }
 }
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/bar.yang
new file mode 100644 (file)
index 0000000..5f409b9
--- /dev/null
@@ -0,0 +1,28 @@
+module bar {
+    yang-version 1;
+    namespace "urn:opendaylight:bar";
+    prefix "bar";
+
+    import baz { prefix bz; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    grouping bar_gr1 {
+        leaf bar1 {
+            type int8;
+        }
+        leaf bar2 {
+            type int16;
+        }
+    }
+
+    grouping bar_gr2 {
+        leaf bar3 {
+            type int32;
+        }
+        uses bar_gr1;
+        uses bz:baz_gr1;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/baz.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/baz.yang
new file mode 100644 (file)
index 0000000..8f4836a
--- /dev/null
@@ -0,0 +1,15 @@
+module baz {
+    yang-version 1;
+    namespace "urn:opendaylight:baz";
+    prefix "baz";
+
+    revision "2013-10-08" {
+    }
+
+    grouping baz_gr1 {
+        leaf baz1 {
+            type uint8;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/foo.yang
new file mode 100644 (file)
index 0000000..b28943d
--- /dev/null
@@ -0,0 +1,24 @@
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight:foo";
+    prefix "foo";
+
+    import bar { prefix br; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    grouping foo_gr1 {
+        container foo_gr1 {
+        }
+        leaf foo2 {
+            type binary;
+        }
+    }
+
+    container nodes {
+        uses foo_gr1;
+        uses "br:bar_gr2";
+    }
+
+}
index 8f3ac4c18b909b73c0b27ccf20f3f33302967623..c3cdc27fb8b77be0176e85fc1220bcdf21f4be05 100644 (file)
@@ -68,6 +68,7 @@ public class YangParserSimpleTest {
         assertEquals(Status.OBSOLETE, data.getStatus());
         assertEquals(0, data.getUnknownSchemaNodes().size());
         // test DataSchemaNode args
+        assertEquals(testModule, data.getParent());
         assertFalse(data.isAugmenting());
         assertFalse(data.isConfiguration());
         ConstraintDefinition constraints = data.getConstraints();
@@ -117,6 +118,7 @@ public class YangParserSimpleTest {
         assertEquals(Status.CURRENT, nodes.getStatus());
         assertEquals(0, nodes.getUnknownSchemaNodes().size());
         // test DataSchemaNode args
+        assertEquals(test, nodes.getParent());
         assertFalse(nodes.isAugmenting());
         assertFalse(nodes.isConfiguration());
 
@@ -169,29 +171,30 @@ public class YangParserSimpleTest {
         // total size = 8: defined 6, inserted by uses 2
         assertEquals(8, nodes.getChildNodes().size());
         AnyXmlSchemaNode text = (AnyXmlSchemaNode)nodes.getDataChildByName("text");
-        assertNotNull(text);
+        assertEquals(nodes, text.getParent());
         ChoiceNode level = (ChoiceNode)nodes.getDataChildByName("level");
-        assertNotNull(level);
+        assertEquals(nodes, level.getParent());
         ContainerSchemaNode node = (ContainerSchemaNode)nodes.getDataChildByName("node");
-        assertNotNull(node);
+        assertEquals(nodes, node.getParent());
         LeafSchemaNode nodesId = (LeafSchemaNode)nodes.getDataChildByName("nodes-id");
-        assertNotNull(nodesId);
+        assertEquals(nodes, nodesId.getParent());
         LeafListSchemaNode added = (LeafListSchemaNode)nodes.getDataChildByName("added");
-        assertNotNull(added);
+        assertEquals(nodes, added.getParent());
         assertEquals(createPath("nodes", "added"), added.getPath());
         assertEquals(createPath("mytype"), added.getType().getPath());
 
         ListSchemaNode links = (ListSchemaNode) nodes.getDataChildByName("links");
-        assertNotNull(links);
+        assertEquals(nodes, links.getParent());
         assertFalse(links.isUserOrdered());
         LeafSchemaNode source = (LeafSchemaNode)nodes.getDataChildByName("source");
-        assertNotNull(source);
+        assertEquals(nodes, source.getParent());
         LeafSchemaNode target = (LeafSchemaNode)nodes.getDataChildByName("target");
-        assertNotNull(target);
+        assertEquals(nodes, target.getParent());
 
         Set<GroupingDefinition> groupings = nodes.getGroupings();
         assertEquals(1, groupings.size());
         GroupingDefinition nodeGroup = groupings.iterator().next();
+        assertEquals(nodes, nodeGroup.getParent());
         QName groupQName = new QName(snNS, snRev, snPref, "node-group");
         assertEquals(groupQName, nodeGroup.getQName());
         SchemaPath nodeGroupPath = TestUtils.createPath(true, snNS, snRev, snPref, "nodes", "node-group");
@@ -200,6 +203,7 @@ public class YangParserSimpleTest {
         Set<UsesNode> uses = nodes.getUses();
         assertEquals(1, uses.size());
         UsesNode use = uses.iterator().next();
+        assertEquals(nodes, use.getParent());
         assertEquals(nodeGroupPath, use.getGroupingPath());
     }
 
index 0d0ddb47bbbedbbda9c4b8d10582db6f2d2a2496..ad720994abf65c659b7927a4ce51b239ad54bd04 100644 (file)
@@ -199,6 +199,7 @@ public class YangParserTest {
         assertEquals(Status.CURRENT, ifEntry.getStatus());
         assertEquals(0, ifEntry.getUnknownSchemaNodes().size());
         // test DataSchemaNode args
+        assertEquals(interfaces, ifEntry.getParent());
         assertFalse(ifEntry.isAugmenting());
         assertTrue(ifEntry.isConfiguration());
         ConstraintDefinition constraints = ifEntry.getConstraints();
@@ -645,6 +646,7 @@ public class YangParserTest {
         Module foo = TestUtils.findModule(modules, "foo");
         ContainerSchemaNode transfer = (ContainerSchemaNode) foo.getDataChildByName("transfer");
         ChoiceNode how = (ChoiceNode) transfer.getDataChildByName("how");
+        assertEquals(transfer, how.getParent());
         Set<ChoiceCaseNode> cases = how.getCases();
         assertEquals(5, cases.size());
         ChoiceCaseNode input = null;
@@ -732,10 +734,12 @@ public class YangParserTest {
         assertEquals(0, notification.getUses().size());
 
         LeafSchemaNode eventClass = (LeafSchemaNode) notification.getDataChildByName("event-class");
+        assertEquals(notification, eventClass.getParent());
         assertTrue(eventClass.getType() instanceof StringType);
         AnyXmlSchemaNode reportingEntity = (AnyXmlSchemaNode) notification.getDataChildByName("reporting-entity");
-        assertNotNull(reportingEntity);
+        assertEquals(notification, reportingEntity.getParent());
         LeafSchemaNode severity = (LeafSchemaNode) notification.getDataChildByName("severity");
+        assertEquals(notification, severity.getParent());
         assertTrue(severity.getType() instanceof StringType);
     }
 
@@ -751,10 +755,15 @@ public class YangParserTest {
         assertEquals("RFC 6241, Section 7.1", rpc.getReference());
 
         ContainerSchemaNode input = rpc.getInput();
-        assertNotNull(input.getDataChildByName("source"));
-        assertNotNull(input.getDataChildByName("filter"));
+        assertEquals(rpc, input.getParent());
+        DataSchemaNode source = input.getDataChildByName("source");
+        assertEquals(input, source.getParent());
+        DataSchemaNode filter = input.getDataChildByName("filter");
+        assertEquals(input, filter.getParent());
         ContainerSchemaNode output = rpc.getOutput();
-        assertNotNull(output.getDataChildByName("data"));
+        assertEquals(rpc, output.getParent());
+        DataSchemaNode data = output.getDataChildByName("data");
+        assertEquals(output, data.getParent());
     }
 
     @Test