1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.tradefed.util; 17 18 import com.android.ddmlib.Log; 19 import com.android.tradefed.util.ClassPathScanner.ExternalClassNameFilter; 20 21 import junit.framework.JUnit4TestAdapter; 22 import junit.framework.Test; 23 import junit.framework.TestCase; 24 import junit.framework.TestSuite; 25 26 import org.junit.runners.Suite.SuiteClasses; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.lang.reflect.Method; 31 import java.net.MalformedURLException; 32 import java.net.URL; 33 import java.net.URLClassLoader; 34 import java.util.Collection; 35 import java.util.Iterator; 36 import java.util.Set; 37 38 /** 39 * A class for loading all JUnit3 tests in a jar file 40 */ 41 public class TestLoader { 42 43 private static final String LOG_TAG = "TestLoader"; 44 45 /** 46 * Creates a {@link Test} containing all the {@link TestCase} found in given jar 47 * 48 * @param testJarFile the jar file to load tests from 49 * @param dependentJars the additional jar files which classes in testJarFile depend on 50 * @return the {@link Test} containing all tests 51 */ loadTests(File testJarFile, Collection<File> dependentJars)52 public Test loadTests(File testJarFile, Collection<File> dependentJars) { 53 ClassPathScanner scanner = new ClassPathScanner(); 54 try { 55 Set<String> classNames = scanner.getEntriesFromJar(testJarFile, 56 new ExternalClassNameFilter()); 57 58 ClassLoader jarClassLoader = buildJarClassLoader(testJarFile, dependentJars); 59 return loadTests(classNames, jarClassLoader); 60 } catch (IOException e) { 61 Log.e(LOG_TAG, String.format("IOException when loading test classes from jar %s", 62 testJarFile.getAbsolutePath())); 63 Log.e(LOG_TAG, e); 64 } 65 return null; 66 } 67 buildJarClassLoader(File jarFile, Collection<File> dependentJars)68 private ClassLoader buildJarClassLoader(File jarFile, Collection<File> dependentJars) 69 throws MalformedURLException { 70 URL[] urls = new URL[dependentJars.size() + 1]; 71 urls[0] = jarFile.toURI().toURL(); 72 Iterator<File> jarIter = dependentJars.iterator(); 73 for (int i=1; i <= dependentJars.size(); i++) { 74 urls[i] = jarIter.next().toURI().toURL(); 75 } 76 return new URLClassLoader(urls); 77 } 78 79 @SuppressWarnings("unchecked") loadTests(Set<String> classNames, ClassLoader classLoader)80 private Test loadTests(Set<String> classNames, ClassLoader classLoader) { 81 TestSuite testSuite = new TestSuite(); 82 for (String className : classNames) { 83 try { 84 Class<?> testClass = Class.forName(className, true, classLoader); 85 if (TestCase.class.isAssignableFrom(testClass)) { 86 testSuite.addTestSuite((Class<? extends TestCase>)testClass); 87 } else if (hasJUnit4Annotation(testClass)) { 88 testSuite.addTest(new JUnit4TestAdapter(testClass)); 89 } 90 } catch (NoClassDefFoundError e) { 91 Log.e(LOG_TAG, e); 92 } catch (ClassNotFoundException e) { 93 Log.e(LOG_TAG, e); 94 } catch (RuntimeException e) { 95 // catch this to prevent one bad test from stopping run 96 Log.e(LOG_TAG, e); 97 } 98 } 99 return testSuite; 100 } 101 102 /** 103 * Helper to device if a class should be loaded as JUnit4. 104 */ hasJUnit4Annotation(Class<?> classObj)105 private boolean hasJUnit4Annotation(Class<?> classObj) { 106 if (classObj.isAnnotationPresent(SuiteClasses.class)) { 107 return true; 108 } 109 for (Method m : classObj.getMethods()) { 110 if (m.isAnnotationPresent(org.junit.Test.class)) { 111 return true; 112 } 113 } 114 return false; 115 } 116 } 117