/*
 * 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);
    }
}
