/*
 * 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}.
 *
 * @deprecated Use
 * <a href="{@docRoot}reference/android/support/test/rule/ServiceTestRule.html">
 * ServiceTestRule</a> instead. New tests should be written using the
 * <a href="{@docRoot}tools/testing-support-library/index.html">Android Testing Support Library</a>.
 */
@Deprecated
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);
    }
}
