blob: 6bbc955eed6b7cebbc6a17105b938e861694307e [file] [log] [blame]
/*
* 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);
}
}