/*
 * 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 android.app.Application;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.test.mock.MockApplication;

import java.lang.reflect.Field;
import java.util.Random;

/**
 * This test case provides a framework in which you can test Service classes in
 * a controlled environment.  It provides basic support for the lifecycle of a
 * Service, and hooks by which you can inject various dependencies and control
 * the environment in which your Service is tested.
 *
 * <p><b>Lifecycle Support.</b>
 * Every Service is designed to be accessed within a specific sequence of
 * calls.  <insert link to Service lifecycle doc here>. 
 * In order to support the lifecycle of a Service, 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 #startService} or {@link #bindService}.  This gives you a chance
 * to set up or adjust any additional framework or test logic before
 * onCreate().</li>
 * <li>When your test calls {@link #startService} or {@link #bindService}
 * the test case will call onCreate(), and then call the corresponding entry point in your service.
 * It will record any parameters or other support values necessary to support the lifecycle.</li>
 * <li>After your test completes, the test case {@link #tearDown} function is
 * automatically called, and it will stop and destroy your service with the appropriate
 * calls (depending on how your test invoked the service.)</li>
 * </ul>
 * 
 * <p><b>Dependency Injection.</b>
 * Every service has two inherent dependencies, the {@link android.content.Context Context} in
 * which it runs, and the {@link android.app.Application Application} with which it is associated.
 * This framework allows you to inject modified, mock, or isolated replacements for these 
 * dependencies, and thus perform a true unit test.
 * 
 * <p>If simply run your tests as-is, your Service will be injected with a fully-functional
 * Context, and a generic {@link android.test.mock.MockApplication MockApplication} object.
 * You can create and inject alternatives to either of these by calling 
 * {@link AndroidTestCase#setContext(Context) setContext()} or 
 * {@link #setApplication setApplication()}.  You must do this <i>before</i> calling
 * startService() or bindService().  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 ServiceTestCase<T extends Service> extends AndroidTestCase {

    Class<T> mServiceClass;

    private Context mSystemContext;
    private Application mApplication;

    public ServiceTestCase(Class<T> serviceClass) {
        mServiceClass = serviceClass;
    }

    private T mService;
    private boolean mServiceAttached = false;
    private boolean mServiceCreated = false;
    private boolean mServiceStarted = false;
    private boolean mServiceBound = false;
    private Intent mServiceIntent = null;
    private int mServiceId;

    /**
     * @return Returns the actual service under test.
     */
    public T getService() {
        return mService;
    }

    /**
     * This will do the work to instantiate the Service under test.  After this, your test 
     * code must also start and stop the service.
     */
    @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();

    }
    
    /**
     * Create the service under test and attach all injected dependencies (Context, Application) to
     * it.  This will be called automatically by {@link #startService} or by {@link #bindService}.
     * If you wish to call {@link AndroidTestCase#setContext(Context) setContext()} or 
     * {@link #setApplication setApplication()}, you must do so  before calling this function.
     */
    protected void setupService() {
        mService = null;
        try {
            mService = mServiceClass.newInstance();
        } catch (Exception e) {
            assertNotNull(mService);
        }
        if (getApplication() == null) {
            setApplication(new MockApplication());
        }
        mService.attach(
                getContext(),
                null,               // ActivityThread not actually used in Service
                mServiceClass.getName(),
                null,               // token not needed when not talking with the activity manager
                getApplication(),
                null                // mocked services don't talk with the activity manager
                );
        
        assertNotNull(mService);
        
        mServiceId = new Random().nextInt();
        mServiceAttached = true;
    }
    
    /**
     * Start the service under test, in the same way as if it was started by
     * {@link android.content.Context#startService Context.startService()}, providing the 
     * arguments it supplied.  If you use this method to start the service, it will automatically
     * be stopped by {@link #tearDown}.
     *  
     * @param intent The Intent as if supplied to {@link android.content.Context#startService}.
     */
    protected void startService(Intent intent) {
        assertFalse(mServiceStarted);
        assertFalse(mServiceBound);
        
        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);
        
        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        mService.onStart(intent, mServiceId);
        
        mServiceStarted = true;
    }
    
    /**
     * Start the service under test, in the same way as if it was started by
     * {@link android.content.Context#bindService Context.bindService()}, providing the 
     * arguments it supplied.
     *  
     * Return the communication channel to the service.  May return null if 
     * clients can not bind to the service.  The returned
     * {@link android.os.IBinder} is usually for a complex interface
     * that has been <a href="{@docRoot}guide/developing/tools/aidl.html">described using
     * aidl</a>. 
     * 
     * Note:  In order to test with this interface, your service must implement a getService()
     * method, as shown in samples.ApiDemos.app.LocalService.

     * @param intent The Intent as if supplied to {@link android.content.Context#bindService}.
     * 
     * @return Return an IBinder for making further calls into the Service.
     */
    protected IBinder bindService(Intent intent) {
        assertFalse(mServiceStarted);
        assertFalse(mServiceBound);
        
        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);
        
        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        // no extras are expected by unbind
        mServiceIntent = intent.cloneFilter();
        IBinder result = mService.onBind(intent);
        
        mServiceBound = true;
        return result;
    }
    
    /**
     * This will make the necessary calls to stop (or unbind) the Service under test, and
     * call onDestroy().  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.
     */
    protected void shutdownService() {
        if (mServiceStarted) {
            mService.stopSelf();
            mServiceStarted = false;
        } else if (mServiceBound) {
            mService.onUnbind(mServiceIntent);
            mServiceBound = false;
        }
        if (mServiceCreated) {
            mService.onDestroy();
        }
    }
    
    /**
     * Shuts down the Service 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 {
        shutdownService();
        mService = 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(ServiceTestCase.class);

        super.tearDown();
    }
    
    /**
     * Set the application for use during the test.  If your test does not call this function,
     * a new {@link android.test.mock.MockApplication MockApplication} object will be generated.
     * 
     * @param application The Application object that will be injected into the Service under test.
     */
    public void setApplication(Application application) {
        mApplication = application;
    }

    /**
     * Return the Application object being used by the Service under test.
     * 
     * @return Returns the application object.
     * 
     * @see #setApplication
     */
    public Application getApplication() {
        return mApplication;
    }
    
    /**
     * Return a real (not mocked or instrumented) system Context that can be used when generating
     * Mock or other Context objects for your Service under test.
     * 
     * @return Returns a reference to a normal Context.
     */
    public Context getSystemContext() {
        return mSystemContext;
    }

    public void testServiceTestCaseSetUpProperly() throws Exception {
        setupService();
        assertNotNull("service should be launched successfully", mService);
    }
}
