| /* |
| * 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.adt.internal.sdk; |
| |
| import com.android.ide.eclipse.adt.internal.sdk.AndroidJarLoader; |
| import com.android.ide.eclipse.adt.internal.sdk.IAndroidClassLoader.IClassDescriptor; |
| import com.android.ide.eclipse.tests.AdtTestData; |
| |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| |
| import junit.framework.TestCase; |
| |
| /** |
| * Unit Test for {@link AndroidJarLoader}. |
| * |
| * Uses the classes jar.example.Class1/Class2 stored in tests/data/jar_example.jar. |
| */ |
| public class AndroidJarLoaderTest extends TestCase { |
| |
| private AndroidJarLoader mFrameworkClassLoader; |
| |
| /** Creates an instance of {@link AndroidJarLoader} on our test data JAR */ |
| @Override |
| public void setUp() throws Exception { |
| String jarfilePath = AdtTestData.getInstance().getTestFilePath( |
| "com/android/ide/eclipse/testdata/jar_example.jar"); //$NON-NLS-1$ |
| mFrameworkClassLoader = new AndroidJarLoader(jarfilePath); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| mFrameworkClassLoader = null; |
| System.gc(); |
| } |
| |
| /** Preloads classes. They should load just fine. */ |
| public final void testPreLoadClasses() throws Exception { |
| mFrameworkClassLoader.preLoadClasses("jar.example.", null, null); //$NON-NLS-1$ |
| HashMap<String, Class<?>> map = getPrivateClassCache(); |
| assertEquals(0, map.size()); |
| HashMap<String,byte[]> data = getPrivateEntryCache(); |
| assertTrue(data.containsKey("jar.example.Class1")); //$NON-NLS-1$ |
| assertTrue(data.containsKey("jar.example.Class2")); //$NON-NLS-1$ |
| assertTrue(data.containsKey("jar.example.Class1$InnerStaticClass1")); //$NON-NLS-1$ |
| assertTrue(data.containsKey("jar.example.Class1$InnerClass2")); //$NON-NLS-1$ |
| assertEquals(4, data.size()); |
| } |
| |
| /** Preloads a class not in the JAR. Preloading does nothing in this case. */ |
| public final void testPreLoadClasses_classNotFound() throws Exception { |
| mFrameworkClassLoader.preLoadClasses("not.a.package.", null, null); //$NON-NLS-1$ |
| HashMap<String, Class<?>> map = getPrivateClassCache(); |
| assertEquals(0, map.size()); |
| HashMap<String,byte[]> data = getPrivateEntryCache(); |
| assertEquals(0, data.size()); |
| } |
| |
| /** Finds a class we just preloaded. It should work. */ |
| public final void testFindClass_classFound() throws Exception { |
| Class<?> c = _findClass(mFrameworkClassLoader, "jar.example.Class2"); //$NON-NLS-1$ |
| assertEquals("jar.example.Class2", c.getName()); //$NON-NLS-1$ |
| HashMap<String, Class<?>> map = getPrivateClassCache(); |
| assertTrue(map.containsKey("jar.example.Class1")); //$NON-NLS-1$ |
| assertTrue(map.containsKey("jar.example.Class2")); //$NON-NLS-1$ |
| assertEquals(2, map.size()); |
| } |
| |
| /** call the protected method findClass */ |
| private Class<?> _findClass(AndroidJarLoader jarLoader, String name) throws Exception { |
| Method findClassMethod = AndroidJarLoader.class.getDeclaredMethod( |
| "findClass", String.class); //$NON-NLS-1$ |
| findClassMethod.setAccessible(true); |
| try { |
| return (Class<?>)findClassMethod.invoke(jarLoader, name); |
| } |
| catch (InvocationTargetException e) { |
| throw (Exception)e.getCause(); |
| } |
| } |
| |
| /** Trying to find a class that we fail to preload should throw a CNFE. */ |
| public final void testFindClass_classNotFound() throws Exception { |
| try { |
| // Will throw ClassNotFoundException |
| _findClass(mFrameworkClassLoader, "not.a.valid.ClassName"); //$NON-NLS-1$ |
| } catch (ClassNotFoundException e) { |
| // check the message in the CNFE |
| assertEquals("not.a.valid.ClassName", e.getMessage()); //$NON-NLS-1$ |
| return; |
| } |
| // Exception not thrown - this is a failure |
| fail("Expected ClassNotFoundException not thrown"); |
| } |
| |
| public final void testFindClassesDerivingFrom() throws Exception { |
| HashMap<String, ArrayList<IClassDescriptor>> found = |
| mFrameworkClassLoader.findClassesDerivingFrom("jar.example.", new String[] { //$NON-NLS-1$ |
| "jar.example.Class1", //$NON-NLS-1$ |
| "jar.example.Class2" }); //$NON-NLS-1$ |
| |
| assertTrue(found.containsKey("jar.example.Class1")); //$NON-NLS-1$ |
| assertTrue(found.containsKey("jar.example.Class2")); //$NON-NLS-1$ |
| assertEquals(2, found.size()); |
| // Only Class2 derives from Class1.. |
| // Class1 and Class1$InnerStaticClass1 derive from Object and are thus ignored. |
| // Class1$InnerClass2 should never be seen either. |
| assertEquals("jar.example.Class2", //$NON-NLS-1$ |
| found.get("jar.example.Class1").get(0).getFullClassName()); //$NON-NLS-1$ |
| assertEquals(1, found.get("jar.example.Class1").size()); //$NON-NLS-1$ |
| assertEquals(0, found.get("jar.example.Class2").size()); //$NON-NLS-1$ |
| } |
| |
| // --- Utilities --- |
| |
| /** |
| * Retrieves the private mFrameworkClassLoader.mClassCache field using reflection. |
| * |
| * @throws NoSuchFieldException |
| * @throws SecurityException |
| * @throws IllegalAccessException |
| * @throws IllegalArgumentException |
| */ |
| @SuppressWarnings("unchecked") |
| private HashMap<String, Class<?> > getPrivateClassCache() |
| throws SecurityException, NoSuchFieldException, |
| IllegalArgumentException, IllegalAccessException { |
| Field field = AndroidJarLoader.class.getDeclaredField("mClassCache"); //$NON-NLS-1$ |
| field.setAccessible(true); |
| return (HashMap<String, Class<?>>) field.get(mFrameworkClassLoader); |
| } |
| |
| /** |
| * Retrieves the private mFrameworkClassLoader.mEntryCache field using reflection. |
| * |
| * @throws NoSuchFieldException |
| * @throws SecurityException |
| * @throws IllegalAccessException |
| * @throws IllegalArgumentException |
| */ |
| @SuppressWarnings("unchecked") |
| private HashMap<String,byte[]> getPrivateEntryCache() |
| throws SecurityException, NoSuchFieldException, |
| IllegalArgumentException, IllegalAccessException { |
| Field field = AndroidJarLoader.class.getDeclaredField("mEntryCache"); //$NON-NLS-1$ |
| field.setAccessible(true); |
| return (HashMap<String, byte[]>) field.get(mFrameworkClassLoader); |
| } |
| } |