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

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 with which you can inject various dependencies and control
 * the environment in which your Service is tested.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
 * <p>For more information about application testing, read the
 * <a href="{@docRoot}guide/topics/testing/index.html">Testing</a> developer guide.</p>
 * </div>
 *
 * <p><b>Lifecycle Support.</b>
 * A Service is accessed with a specific sequence of
 * calls, as described in the
 * <a href="http://developer.android.com/guide/topics/fundamentals/services.html">Services</a>
 * document. In order to support the lifecycle of a Service,
 * <code>ServiceTestCase</code> enforces this protocol:
 *
 * <ul>
 *      <li>
 *          The {@link #setUp()} method is called before each test method. The base implementation
 *          gets the system context. If you override <code>setUp()</code>, you must call
 *          <code>super.setUp()</code> as the first statement in your override.
 *      </li>
 *      <li>
 *          The test case waits to call {@link android.app.Service#onCreate()} until one of your
 *          test methods calls {@link #startService} or {@link #bindService}.  This gives you an
 *          opportunity to set up or adjust any additional framework or test logic before you test
 *          the running service.
 *      </li>
 *      <li>
 *          When one of your test methods calls {@link #startService ServiceTestCase.startService()}
 *          or {@link #bindService  ServiceTestCase.bindService()}, the test case calls
 *          {@link android.app.Service#onCreate() Service.onCreate()} and then calls either
 *          {@link android.app.Service#startService(Intent) Service.startService(Intent)} or
 *          {@link android.app.Service#bindService(Intent, ServiceConnection, int)
 *          Service.bindService(Intent, ServiceConnection, int)}, as appropriate. It also stores
 *          values needed to track and support the lifecycle.
 *      </li>
 *      <li>
 *          After each test method finishes, the test case calls the {@link #tearDown} method. This
 *          method stops and destroys the service with the appropriate calls, depending on how the
 *          service was started. If you override <code>tearDown()</code>, your must call the
 *          <code>super.tearDown()</code> as the last statement in your override.
 *      </li>
 * </ul>
 *
 * <p>
 *      <strong>Dependency Injection.</strong>
 *      A service has two inherent dependencies, its {@link android.content.Context Context} and its
 *      associated {@link android.app.Application Application}. The ServiceTestCase framework
 *      allows you to inject modified, mock, or isolated replacements for these dependencies, and
 *      thus perform unit tests with controlled dependencies in an isolated environment.
 * </p>
 * <p>
 *      By default, the test case is injected with a full system context and a generic
 *      {@link android.test.mock.MockApplication MockApplication} object. You can inject
 *      alternatives to either of these by invoking
 *      {@link AndroidTestCase#setContext(Context) setContext()} or
 *      {@link #setApplication setApplication()}.  You must do this <em>before</em> 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},
 *      {@link android.content.ContextWrapper ContextWrapper}, and
 *      {@link android.test.IsolatedContext}.
 */
public abstract class ServiceTestCase<T extends Service> extends AndroidTestCase {

    Class<T> mServiceClass;

    private Context mSystemContext;
    private Application mApplication;

    /**
     * Constructor
     * @param serviceClass The type of the service under test.
     */
    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 An instance of the service under test. This instance is created automatically when
     * a test calls {@link #startService} or {@link #bindService}.
     */
    public T getService() {
        return mService;
    }

    /**
     * Gets the current system context and stores it.
     *
     * Extend this method to do your own test initialization. If you do so, you
     * must call <code>super.setUp()</code> as the first statement in your override. The method is
     * called before each test method is executed.
     */
    @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();

    }

    /**
     * Creates the service under test and attaches all injected dependencies
     * (Context, Application) to it.  This is called automatically by {@link #startService} or
     * by {@link #bindService}.
     * If you need to call {@link AndroidTestCase#setContext(Context) setContext()} or
     * {@link #setApplication setApplication()}, do so before calling this method.
     */
    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;
    }

    /**
     * Starts the service under test, in the same way as if it were started by
     * {@link android.content.Context#startService(Intent) Context.startService(Intent)} with
     * an {@link android.content.Intent} that identifies a service.
     * If you use this method to start the service, it is automatically stopped by
     * {@link #tearDown}.
     *
     * @param intent An Intent that identifies a service, of the same form as the Intent passed to
     * {@link android.content.Context#startService(Intent) Context.startService(Intent)}.
     */
    protected void startService(Intent intent) {
        if (!mServiceAttached) {
            setupService();
        }
        assertNotNull(mService);

        if (!mServiceCreated) {
            mService.onCreate();
            mServiceCreated = true;
        }
        mService.onStartCommand(intent, 0, mServiceId);

        mServiceStarted = true;
    }

    /**
     * <p>
     *      Starts the service under test, in the same way as if it were started by
     *      {@link android.content.Context#bindService(Intent, ServiceConnection, int)
     *      Context.bindService(Intent, ServiceConnection, flags)} with an
     *      {@link android.content.Intent} that identifies a service.
     * </p>
     * <p>
     *      Notice that the parameters are different. You do not provide a
     *      {@link android.content.ServiceConnection} object or the flags parameter. Instead,
     *      you only provide the Intent. The method returns an object whose type is a
     *      subclass of {@link android.os.IBinder}, or null if the method fails. An IBinder
     *      object refers to a communication channel between the application and
     *      the service. The flag is assumed to be {@link android.content.Context#BIND_AUTO_CREATE}.
     * </p>
     * <p>
     *      See <a href="{@docRoot}guide/components/aidl.html">Designing a Remote Interface
     *      Using AIDL</a> for more information about the communication channel object returned
     *      by this method.
     * </p>
     * Note:  To be able to use bindService in a test, the service must implement getService()
     * method. An example of this is in the ApiDemos sample application, in the
     * LocalService demo.
     *
     * @param intent An Intent object of the form expected by
     * {@link android.content.Context#bindService}.
     *
     * @return An object whose type is a subclass of IBinder, for making further calls into
     * the service.
     */
    protected IBinder bindService(Intent intent) {
        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;
    }

    /**
     * Makes the necessary calls to stop (or unbind) the service under test, and
     * calls onDestroy().  Ordinarily this is called automatically (by {@link #tearDown}, but
     * you can call it directly from your test in order to check for proper shutdown behavior.
     */
    protected void shutdownService() {
        if (mServiceStarted) {
            mService.stopSelf();
            mServiceStarted = false;
        } else if (mServiceBound) {
            mService.onUnbind(mServiceIntent);
            mServiceBound = false;
        }
        if (mServiceCreated) {
            mService.onDestroy();
            mServiceCreated = false;
        }
    }

    /**
     * <p>
     *      Shuts down the service under test.  Ensures all resources are cleaned up and
     *      garbage collected before moving on to the next test. This method is called after each
     *      test method.
     * </p>
     * <p>
     *      Subclasses that override this method must call <code>super.tearDown()</code> as their
     *      last statement.
     * </p>
     *
     * @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();
    }

    /**
     * Sets the application that is used during the test.  If you do not call this method,
     * a new {@link android.test.mock.MockApplication MockApplication} object is used.
     *
     * @param application The Application object that is used by the service under test.
     *
     * @see #getApplication()
     */
    public void setApplication(Application application) {
        mApplication = application;
    }

    /**
     * Returns the Application object in use by the service under test.
     *
     * @return The application object.
     *
     * @see #setApplication
     */
    public Application getApplication() {
        return mApplication;
    }

    /**
     * Returns the real system context that is saved by {@link #setUp()}. Use it to create
     * mock or other types of context objects for the service under test.
     *
     * @return A normal system context.
     */
    public Context getSystemContext() {
        return mSystemContext;
    }

    /**
     * Tests that {@link #setupService()} runs correctly and issues an
     * {@link junit.framework.Assert#assertNotNull(String, Object)} if it does.
     * You can override this test method if you wish.
     *
     * @throws Exception
     */
    public void testServiceTestCaseSetUpProperly() throws Exception {
        setupService();
        assertNotNull("service should be launched successfully", mService);
    }
}
