/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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 android.test;

import java.lang.reflect.Field;

import android.app.Application;
import android.app.Instrumentation;
import android.content.Context;

/**
 * This test case provides a framework in which you can test Application classes in
 * a controlled environment.  It provides basic support for the lifecycle of a
 * Application, and hooks by which you can inject various dependencies and control
 * the environment in which your Application is tested.
 *
 * <p><b>Lifecycle Support.</b>
 * Every Application is designed to be accessed within a specific sequence of
 * method calls (see {@link android.app.Application} for more details).
 * In order to support the lifecycle of a Application, this test case will make the
 * following calls at the following times.
 *
 * <ul><li>The test case will not call onCreate() until your test calls 
 * {@link #createApplication()}.  This gives you a chance
 * to set up or adjust any additional framework or test logic before
 * onCreate().</li>
 * <li>After your test completes, the test case {@link #tearDown} method is
 * automatically called, and it will stop & destroy your application by calling its
 * onDestroy() method.</li>
 * </ul>
 * 
 * <p><b>Dependency Injection.</b>
 * Every Application has one inherent dependency, the {@link android.content.Context Context} in
 * which it runs.
 * This framework allows you to inject a modified, mock, or isolated replacement for this 
 * dependencies, and thus perform a true unit test.
 * 
 * <p>If simply run your tests as-is, your Application will be injected with a fully-functional
 * Context.
 * You can create and inject alternative types of Contexts by calling 
 * {@link AndroidTestCase#setContext(Context) setContext()}.  You must do this <i>before</i> calling
 * startApplication().  The test framework provides a
 * number of alternatives for Context, including {@link android.test.mock.MockContext MockContext}, 
 * {@link android.test.RenamingDelegatingContext RenamingDelegatingContext}, and 
 * {@link android.content.ContextWrapper ContextWrapper}.
 */
public abstract class ApplicationTestCase<T extends Application> extends AndroidTestCase {

    Class<T> mApplicationClass;

    private Context mSystemContext;

    public ApplicationTestCase(Class<T> applicationClass) {
        mApplicationClass = applicationClass;
    }

    private T mApplication;
    private boolean mAttached = false;
    private boolean mCreated = false;

    /**
     * @return Returns the actual Application under test.
     */
    public T getApplication() {
        return mApplication;
    }

    /**
     * This will do the work to instantiate the Application under test.  After this, your test 
     * code must also start and stop the Application.
     */
    @Override
    protected void setUp() throws Exception {
        super.setUp();
        
        // get the real context, before the individual tests have a chance to muck with it
        mSystemContext = getContext();
    }
    
    /**
     * Load and attach the application under test.
     */
    private void setupApplication() {
        mApplication = null;
        try {
            mApplication = (T) Instrumentation.newApplication(mApplicationClass, getContext());
        } catch (Exception e) {
            assertNotNull(mApplication);
        }
        mAttached = true;
    }
    
    /**
     * Start the Application under test, in the same way as if it was started by the system.  
     * If you use this method to start the Application, it will automatically
     * be stopped by {@link #tearDown}.  If you wish to inject a specialized Context for your
     * test, by calling {@link AndroidTestCase#setContext(Context) setContext()}, 
     * you must do so  before calling this method.
     */
    final protected void createApplication() {
        assertFalse(mCreated);
        
        if (!mAttached) {
            setupApplication();
        }
        assertNotNull(mApplication);
        
        mApplication.onCreate();
        mCreated = true;
    }
    
    /**
     * This will make the necessary calls to terminate the Application under test (it will
     * call onTerminate().  Ordinarily this will be called automatically (by {@link #tearDown}, but
     * you can call it directly from your test in order to check for proper shutdown behaviors.
     */
    final protected void terminateApplication() {
        if (mCreated) {
            mApplication.onTerminate();
        }
    }
    
    /**
     * Shuts down the Application under test.  Also makes sure all resources are cleaned up and 
     * garbage collected before moving on to the next
     * test.  Subclasses that override this method should make sure they call super.tearDown()
     * at the end of the overriding method.
     * 
     * @throws Exception
     */
    @Override
    protected void tearDown() throws Exception {
        terminateApplication();
        mApplication = null;

        // Scrub out members - protects against memory leaks in the case where someone 
        // creates a non-static inner class (thus referencing the test case) and gives it to
        // someone else to hold onto
        scrubClass(ApplicationTestCase.class);

        super.tearDown();
    }

    /**
     * Return a real (not mocked or instrumented) system Context that can be used when generating
     * Mock or other Context objects for your Application under test.
     * 
     * @return Returns a reference to a normal Context.
     */
    public Context getSystemContext() {
        return mSystemContext;
    }

    /**
     * This test simply confirms that the Application class can be instantiated properly.
     * 
     * @throws Exception
     */
    final public void testApplicationTestCaseSetUpProperly() throws Exception {
        setupApplication();
        assertNotNull("Application class could not be instantiated successfully", mApplication);
    }
}
