/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import com.android.cts.util.AbiUtils;

import org.junit.runner.RunWith;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import vogar.Expectation;
import vogar.ExpectationStore;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import junit.framework.TestCase;

public class CollectAllTests extends DescriptionGenerator {

    private static final String ATTRIBUTE_RUNNER = "runner";
    private static final String ATTRIBUTE_PACKAGE = "appPackageName";
    private static final String ATTRIBUTE_NS = "appNameSpace";
    private static final String ATTRIBUTE_TARGET = "targetNameSpace";
    private static final String ATTRIBUTE_TARGET_BINARY = "targetBinaryName";
    private static final String ATTRIBUTE_HOST_SIDE_ONLY = "hostSideOnly";
    private static final String ATTRIBUTE_VM_HOST_TEST = "vmHostTest";
    private static final String ATTRIBUTE_JAR_PATH = "jarPath";
    private static final String ATTRIBUTE_JAVA_PACKAGE_FILTER = "javaPackageFilter";

    private static final String JAR_PATH = "LOCAL_JAR_PATH :=";
    private static final String TEST_TYPE = "LOCAL_TEST_TYPE :";

    public static void main(String[] args) {
        if (args.length < 5 || args.length > 7) {
            System.err.println("usage: CollectAllTests <output-file> <manifest-file> <jar-file> "
                               + "<java-package> <architecture> [expectation-dir [makefile-file]]");
            if (args.length != 0) {
                System.err.println("received:");
                for (String arg : args) {
                    System.err.println("  " + arg);
                }
            }
            System.exit(1);
        }

        final String outputPathPrefix = args[0];
        File manifestFile = new File(args[1]);
        String jarFileName = args[2];
        final String javaPackageFilterArg = args[3] != null ? args[3].replaceAll("\\s+", "") : "";
        final String[] javaPackagePrefixes;
        // Validate the javaPackageFilter value if non-empty.
        if (!javaPackageFilterArg.isEmpty()) {
            javaPackagePrefixes = javaPackageFilterArg.split(":");
            for (int i = 0; i < javaPackagePrefixes.length; ++i) {
                final String javaPackageFilter = javaPackagePrefixes[i];
                if (!isValidJavaPackage(javaPackageFilter)) {
                    System.err.println("Invalid " + ATTRIBUTE_JAVA_PACKAGE_FILTER + ": " +
                           javaPackageFilter);
                    System.exit(1);
                    return;
                } else {
                    javaPackagePrefixes[i] = javaPackageFilter.trim() + ".";
                }
            }
        } else {
            javaPackagePrefixes = new String[0];
        }

        String architecture = args[4];
        if (architecture == null || architecture.equals("")) {
            System.err.println("Invalid architecture");
            System.exit(1);
            return;
        }
        String libcoreExpectationDir = (args.length > 5) ? args[5] : null;
        String androidMakeFile = (args.length > 6) ? args[6] : null;

        final TestType testType = TestType.getTestType(androidMakeFile);

        Document manifest;
        try {
            manifest = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
                  new FileInputStream(manifestFile));
        } catch (Exception e) {
            System.err.println("cannot open manifest " + manifestFile);
            e.printStackTrace();
            System.exit(1);
            return;
        }

        Element documentElement = manifest.getDocumentElement();
        documentElement.getAttribute("package");
        final String runner = getElementAttribute(documentElement,
                                                  "instrumentation",
                                                  "android:name");
        final String packageName = documentElement.getAttribute("package");
        final String target = getElementAttribute(documentElement,
                                                  "instrumentation",
                                                  "android:targetPackage");

        String outputXmlFile = outputPathPrefix + ".xml";
        final String xmlName = new File(outputPathPrefix).getName();
        XMLGenerator xmlGenerator;
        try {
            xmlGenerator = new XMLGenerator(outputXmlFile) {
                {
                    Node testPackageElem = mDoc.getDocumentElement();

                    setAttribute(testPackageElem, ATTRIBUTE_NAME, xmlName);
                    setAttribute(testPackageElem, ATTRIBUTE_RUNNER, runner);
                    setAttribute(testPackageElem, ATTRIBUTE_PACKAGE, packageName);
                    setAttribute(testPackageElem, ATTRIBUTE_NS, packageName);
                    setAttribute(testPackageElem, ATTRIBUTE_JAVA_PACKAGE_FILTER, javaPackageFilterArg);

                    if (testType.type == TestType.HOST_SIDE_ONLY) {
                        setAttribute(testPackageElem, ATTRIBUTE_HOST_SIDE_ONLY, "true");
                        setAttribute(testPackageElem, ATTRIBUTE_JAR_PATH, testType.jarPath);
                    }

                    if (testType.type == TestType.VM_HOST_TEST) {
                        setAttribute(testPackageElem, ATTRIBUTE_VM_HOST_TEST, "true");
                        setAttribute(testPackageElem, ATTRIBUTE_JAR_PATH, testType.jarPath);
                    }

                    if (!packageName.equals(target)) {
                        setAttribute(testPackageElem, ATTRIBUTE_TARGET, target);
                        setAttribute(testPackageElem, ATTRIBUTE_TARGET_BINARY, target);
                    }
                }
            };
        } catch (ParserConfigurationException e) {
            System.err.println("Can't initialize XML Generator " + outputXmlFile);
            System.exit(1);
            return;
        }

        ExpectationStore libcoreVogarExpectationStore;
        ExpectationStore ctsVogarExpectationStore;

        try {
            libcoreVogarExpectationStore
                    = VogarUtils.provideExpectationStore(libcoreExpectationDir);
            ctsVogarExpectationStore = VogarUtils.provideExpectationStore(CTS_EXPECTATION_DIR);
        } catch (IOException e) {
            System.err.println("Can't initialize vogar expectation store from "
                               + libcoreExpectationDir);
            e.printStackTrace(System.err);
            System.exit(1);
            return;
        }
        ExpectationStore[] expectations = new ExpectationStore[] {
            libcoreVogarExpectationStore, ctsVogarExpectationStore
        };

        JarFile jarFile = null;
        try {
            jarFile = new JarFile(jarFileName);
        } catch (Exception e) {
            System.err.println("cannot open jarfile " + jarFileName);
            e.printStackTrace();
            System.exit(1);
        }

        Map<String,TestClass> testCases = new LinkedHashMap<String, TestClass>();

        Enumeration<JarEntry> jarEntries = jarFile.entries();
        while (jarEntries.hasMoreElements()) {
            JarEntry jarEntry = jarEntries.nextElement();
            String name = jarEntry.getName();
            if (!name.endsWith(".class")) {
                continue;
            }
            String className
                    = name.substring(0, name.length() - ".class".length()).replace('/', '.');

            boolean matchesPrefix = false;
            if (javaPackagePrefixes.length > 0) {
                for (String javaPackagePrefix : javaPackagePrefixes) {
                    if (className.startsWith(javaPackagePrefix)) {
                        matchesPrefix = true;
                    }
                }
            } else {
                matchesPrefix = true;
            }

            if (!matchesPrefix) {
                continue;
            }

            try {
                Class<?> klass = Class.forName(className,
                                               false,
                                               CollectAllTests.class.getClassLoader());
                final int modifiers = klass.getModifiers();
                if (Modifier.isAbstract(modifiers) || !Modifier.isPublic(modifiers)) {
                    continue;
                }

                final boolean isJunit4Class = isJunit4Class(klass);
                if (!isJunit4Class && !isJunit3Test(klass)) {
                    continue;
                }

                try {
                    klass.getConstructor(new Class<?>[] { String.class } );
                    addToTests(expectations, architecture, testCases, klass);
                    continue;
                } catch (NoSuchMethodException e) {
                } catch (SecurityException e) {
                    System.out.println("Known bug (Working as intended): problem with class "
                            + className);
                    e.printStackTrace();
                }

                try {
                    klass.getConstructor(new Class<?>[0]);
                    addToTests(expectations, architecture, testCases, klass);
                    continue;
                } catch (NoSuchMethodException e) {
                } catch (SecurityException e) {
                    System.out.println("Known bug (Working as intended): problem with class "
                            + className);
                    e.printStackTrace();
                }
            } catch (ClassNotFoundException e) {
                System.out.println("class not found " + className);
                e.printStackTrace();
                System.exit(1);
            }
        }

        for (Iterator<TestClass> iterator = testCases.values().iterator(); iterator.hasNext();) {
            TestClass type = iterator.next();
            xmlGenerator.addTestClass(type);
        }

        try {
            xmlGenerator.dump();
        } catch (Exception e) {
            System.err.println("cannot dump xml to " + outputXmlFile);
            e.printStackTrace();
            System.exit(1);
        }
    }

    private static class TestType {
        private static final int HOST_SIDE_ONLY = 1;
        private static final int DEVICE_SIDE_ONLY = 2;
        private static final int VM_HOST_TEST = 3;

        private final int type;
        private final String jarPath;

        private TestType (int type, String jarPath) {
            this.type = type;
            this.jarPath = jarPath;
        }

        private static TestType getTestType(String makeFileName) {
            if (makeFileName == null || makeFileName.isEmpty()) {
                return new TestType(DEVICE_SIDE_ONLY, null);
            }
            int type = TestType.DEVICE_SIDE_ONLY;
            String jarPath = null;
            try {
                BufferedReader reader = new BufferedReader(new FileReader(makeFileName));
                String line;

                while ((line = reader.readLine())!=null) {
                    if (line.startsWith(TEST_TYPE)) {
                        if (line.indexOf(ATTRIBUTE_VM_HOST_TEST) >= 0) {
                            type = VM_HOST_TEST;
                        } else {
                            type = HOST_SIDE_ONLY;
                        }
                    } else if (line.startsWith(JAR_PATH)) {
                        jarPath = line.substring(JAR_PATH.length(), line.length()).trim();
                    }
                }
                reader.close();
            } catch (IOException e) {
            }
            return new TestType(type, jarPath);
        }
    }

    private static Element getElement(Element element, String tagName) {
        NodeList elements = element.getElementsByTagName(tagName);
        if (elements.getLength() > 0) {
            return (Element) elements.item(0);
        } else {
            return null;
        }
    }

    private static String getElementAttribute(Element element,
                                              String elementName,
                                              String attributeName) {
        Element e = getElement(element, elementName);
        if (e != null) {
            return e.getAttribute(attributeName);
        } else {
            return "";
        }
    }

    private static String getKnownFailure(final Class<?> testClass,
            final String testName) {
        return getAnnotation(testClass, testName, KNOWN_FAILURE);
    }

    private static boolean isKnownFailure(final Class<?> testClass,
            final String testName) {
        return getAnnotation(testClass, testName, KNOWN_FAILURE) != null;
    }

    private static boolean isSuppressed(final Class<?> testClass,
            final String testName)  {
        return getAnnotation(testClass, testName, SUPPRESSED_TEST) != null;
    }

    private static String getAnnotation(final Class<?> testClass,
            final String testName, final String annotationName) {
        try {
            Method testMethod = testClass.getMethod(testName, (Class[])null);
            Annotation[] annotations = testMethod.getAnnotations();
            for (Annotation annot : annotations) {

                if (annot.annotationType().getName().equals(annotationName)) {
                    String annotStr = annot.toString();
                    String knownFailure = null;
                    if (annotStr.contains("(value=")) {
                        knownFailure =
                            annotStr.substring(annotStr.indexOf("=") + 1,
                                    annotStr.length() - 1);

                    }

                    if (knownFailure == null) {
                        knownFailure = "true";
                    }

                    return knownFailure;
                }

            }

        } catch (NoSuchMethodException e) {
        }

        return null;
    }

    private static void addToTests(ExpectationStore[] expectations,
                                   String architecture,
                                   Map<String,TestClass> testCases,
                                   Class<?> testClass) {
        Set<String> testNames = new HashSet<String>();

        boolean isJunit3Test = isJunit3Test(testClass);

        Method[] testMethods = testClass.getMethods();
        for (Method testMethod : testMethods) {
            String testName = testMethod.getName();
            if (testNames.contains(testName)) {
                continue;
            }

            /* Make sure the method has the right signature. */
            if (!Modifier.isPublic(testMethod.getModifiers())) {
                continue;
            }
            if (!testMethod.getReturnType().equals(Void.TYPE)) {
                continue;
            }
            if (testMethod.getParameterTypes().length != 0) {
                continue;
            }

            if ((isJunit3Test && !testName.startsWith("test"))
                    || (!isJunit3Test && !isJunit4TestMethod(testMethod))) {
                continue;
            }

            testNames.add(testName);
            addToTests(expectations, architecture, testCases, testClass, testName);
        }
    }

    private static void addToTests(ExpectationStore[] expectations,
                                   String architecture,
                                   Map<String,TestClass> testCases,
                                   Class<?> test,
                                   String testName) {

        String testClassName = test.getName();
        String knownFailure = getKnownFailure(test, testName);

        if (isKnownFailure(test, testName)) {
            System.out.println("ignoring known failure: " + test + "#" + testName);
            return;
        } else if (isSuppressed(test, testName)) {
            System.out.println("ignoring suppressed test: " + test + "#" + testName);
            return;
        } else if (VogarUtils.isVogarKnownFailure(expectations,
                                                  testClassName,
                                                  testName)) {
            System.out.println("ignoring expectation known failure: " + test
                               + "#" + testName);
            return;
        }

        Set<String> supportedAbis = VogarUtils.extractSupportedAbis(architecture,
                                                                    expectations,
                                                                    testClassName,
                                                                    testName);
        int timeoutInMinutes = VogarUtils.timeoutInMinutes(expectations,
                                                           testClassName,
                                                           testName);
        TestClass testClass;
        if (testCases.containsKey(testClassName)) {
            testClass = testCases.get(testClassName);
        } else {
            testClass = new TestClass(testClassName, new ArrayList<TestMethod>());
            testCases.put(testClassName, testClass);
        }

        testClass.mCases.add(new TestMethod(testName, "", "", supportedAbis,
              knownFailure, false, false, timeoutInMinutes));
    }

    private static boolean isJunit3Test(Class<?> klass) {
        return TestCase.class.isAssignableFrom(klass);
    }

    private static boolean isJunit4Class(Class<?> klass) {
        for (Annotation a : klass.getAnnotations()) {
            if (RunWith.class.isAssignableFrom(a.annotationType())) {
                // @RunWith is currently not supported for CTS tests because tradefed cannot handle
                // a single test spawning other tests with different names.
                System.out.println("Skipping test class " + klass.getName()
                        + ": JUnit4 @RunWith is not supported");
                return false;
            }
        }

        for (Method m : klass.getMethods()) {
            if (isJunit4TestMethod(m)) {
                return true;
            }
        }

        return false;
    }

    private static boolean isJunit4TestMethod(Method method) {
        for (Annotation a : method.getAnnotations()) {
            if (org.junit.Test.class.isAssignableFrom(a.annotationType())) {
                return true;
            }
        }

        return false;
    }

    /**
     * Determines if a given string is a valid java package name
     * @param javaPackageName
     * @return true if it is valid, false otherwise
     */
    private static boolean isValidJavaPackage(String javaPackageName) {
        String[] strSections = javaPackageName.split(".");
        for (String strSection : strSections) {
          if (!isValidJavaIdentifier(strSection)) {
              return false;
          }
        }
        return true;
    }

    /**
     * Determines if a given string is a valid java identifier.
     * @param javaIdentifier
     * @return true if it is a valid identifier, false otherwise
     */
    private static boolean isValidJavaIdentifier(String javaIdentifier) {
        if (javaIdentifier.length() == 0 ||
                !Character.isJavaIdentifierStart(javaIdentifier.charAt(0))) {
            return false;
        }
        for (int i = 1; i < javaIdentifier.length(); i++) {
            if (!Character.isJavaIdentifierPart(javaIdentifier.charAt(i))) {
                return false;
            }
        }
        return true;
    }
}
