/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
 *
 * 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.
 */
package com.android.ide.eclipse.tests;

import org.eclipse.core.runtime.Plugin;

import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.Enumeration;

import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 * Class for collecting all test cases in an eclipse plugin
 *
 */
public class EclipseTestCollector {

    /**
     * Constructor
     */
    public EclipseTestCollector() {

    }

    /**
     * Searches through given plugin, adding all TestCase classes to given suite
     * @param suite - TestSuite to add to
     * @param plugin - Plugin to search for tests
     * @param expectedPackage - expected package for tests. Only test classes
     *  that start with this package name will be added to suite
     */
    @SuppressWarnings({"cast", "unchecked"})
    public void addTestCases(TestSuite suite, Plugin plugin, String expectedPackage) {
        if (plugin != null) {
            Enumeration<?> entries = plugin.getBundle().findEntries("/", "*.class", true);

            while (entries.hasMoreElements()) {
                URL entry = (URL)entries.nextElement();
                String filePath = entry.getPath().replace(".class", "");
                try {
                  Class<?> testClass = getClass(filePath, expectedPackage);
                  if (isTestClass(testClass)) {
                      // In Eclipse 3.6 RCP Windows-x64, the signature has changed from
                      //    addTestSuite(Class)
                      // to:
                      //    addTestSuite(Class<? extends TestCase>)
                      // which is enough to create an error. To solve it, we cast into the
                      // generics expected by the JUnit framework used by 3.6 and suppress the
                      // warnings generated by the compiler under 3.5
                      suite.addTestSuite((Class<? extends TestCase>)testClass);
                  }
                }
                catch (ClassNotFoundException e) {
                  // ignore, this is not the class we're looking for
                  //sLogger.log(Level.INFO, "Could not load class " + filePath);
              }
            }
        }
    }

    /**
     * Returns true if given class should be added to suite
     */
    protected boolean isTestClass(Class<?> testClass) {
        return TestCase.class.isAssignableFrom(testClass) &&
          Modifier.isPublic(testClass.getModifiers()) &&
          hasPublicConstructor(testClass);
    }

    /**
     * Returns true if given class has a public constructor
     */
    @SuppressWarnings({"unchecked", "cast"})
    protected boolean hasPublicConstructor(Class<?> testClass) {
        try {
            // In Eclipse 3.6 RCP Windows-x64, the signature has changed from
            //    getTestConstructor(Class)
            // to:
            //    getTestConstructor(Class<? extends TestCase>)
            // which is enough to create an error. To solve it, we cast into the
            // generics expected by the JUnit framework used by 3.6 and suppress the
            // warnings generated by the compiler under 3.5
            TestSuite.getTestConstructor((Class<? extends TestCase>) testClass);
        } catch(NoSuchMethodException e) {
            return false;
        }
        return true;
    }

    /**
     * Load the class given by the plugin aka bundle file path
     * @param filePath - path of class in bundle
     * @param expectedPackage - expected package of class
     * @throws ClassNotFoundException
     */
    protected Class<?> getClass(String filePath, String expectedPackage) throws ClassNotFoundException {
        String dotPath = filePath.replace('/', '.');
        // remove the output folders, by finding where package name starts
        int index = dotPath.indexOf(expectedPackage);
        if (index == -1) {
            throw new ClassNotFoundException();
        }
        String packagePath = dotPath.substring(index);
        return Class.forName(packagePath);
    }
}
