Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Eclipse Public License, Version 1.0 (the "License"); you
      5  * may not use this file except in compliance with the License. You may obtain a
      6  * copy of the License at
      7  *
      8  * http://www.eclipse.org/org/documents/epl-v10.php
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 package com.android.ide.eclipse.tests;
     17 
     18 import org.eclipse.core.runtime.Plugin;
     19 
     20 import java.lang.reflect.Modifier;
     21 import java.net.URL;
     22 import java.util.Enumeration;
     23 
     24 import junit.framework.TestCase;
     25 import junit.framework.TestSuite;
     26 
     27 /**
     28  * Class for collecting all test cases in an eclipse plugin
     29  *
     30  */
     31 public class EclipseTestCollector {
     32 
     33     /**
     34      * Constructor
     35      */
     36     public EclipseTestCollector() {
     37 
     38     }
     39 
     40     /**
     41      * Searches through given plugin, adding all TestCase classes to given suite
     42      * @param suite - TestSuite to add to
     43      * @param plugin - Plugin to search for tests
     44      * @param expectedPackage - expected package for tests. Only test classes
     45      *  that start with this package name will be added to suite
     46      */
     47     @SuppressWarnings({"cast", "unchecked"})
     48     public void addTestCases(TestSuite suite, Plugin plugin, String expectedPackage) {
     49         if (plugin != null) {
     50             Enumeration<?> entries = plugin.getBundle().findEntries("/", "*.class", true);
     51 
     52             while (entries.hasMoreElements()) {
     53                 URL entry = (URL)entries.nextElement();
     54                 String filePath = entry.getPath().replace(".class", "");
     55                 try {
     56                   Class<?> testClass = getClass(filePath, expectedPackage);
     57                   if (isTestClass(testClass)) {
     58                       // In Eclipse 3.6 RCP Windows-x64, the signature has changed from
     59                       //    addTestSuite(Class)
     60                       // to:
     61                       //    addTestSuite(Class<? extends TestCase>)
     62                       // which is enough to create an error. To solve it, we cast into the
     63                       // generics expected by the JUnit framework used by 3.6 and suppress the
     64                       // warnings generated by the compiler under 3.5
     65                       suite.addTestSuite((Class<? extends TestCase>)testClass);
     66                   }
     67                 }
     68                 catch (ClassNotFoundException e) {
     69                   // ignore, this is not the class we're looking for
     70                   //sLogger.log(Level.INFO, "Could not load class " + filePath);
     71               }
     72             }
     73         }
     74     }
     75 
     76     /**
     77      * Returns true if given class should be added to suite
     78      */
     79     protected boolean isTestClass(Class<?> testClass) {
     80         return TestCase.class.isAssignableFrom(testClass) &&
     81           Modifier.isPublic(testClass.getModifiers()) &&
     82           hasPublicConstructor(testClass);
     83     }
     84 
     85     /**
     86      * Returns true if given class has a public constructor
     87      */
     88     @SuppressWarnings({"unchecked", "cast"})
     89     protected boolean hasPublicConstructor(Class<?> testClass) {
     90         try {
     91             // In Eclipse 3.6 RCP Windows-x64, the signature has changed from
     92             //    getTestConstructor(Class)
     93             // to:
     94             //    getTestConstructor(Class<? extends TestCase>)
     95             // which is enough to create an error. To solve it, we cast into the
     96             // generics expected by the JUnit framework used by 3.6 and suppress the
     97             // warnings generated by the compiler under 3.5
     98             TestSuite.getTestConstructor((Class<? extends TestCase>) testClass);
     99         } catch(NoSuchMethodException e) {
    100             return false;
    101         }
    102         return true;
    103     }
    104 
    105     /**
    106      * Load the class given by the plugin aka bundle file path
    107      * @param filePath - path of class in bundle
    108      * @param expectedPackage - expected package of class
    109      * @throws ClassNotFoundException
    110      */
    111     protected Class<?> getClass(String filePath, String expectedPackage) throws ClassNotFoundException {
    112         String dotPath = filePath.replace('/', '.');
    113         // remove the output folders, by finding where package name starts
    114         int index = dotPath.indexOf(expectedPackage);
    115         if (index == -1) {
    116             throw new ClassNotFoundException();
    117         }
    118         String packagePath = dotPath.substring(index);
    119         return Class.forName(packagePath);
    120     }
    121 }
    122