/*
 * Copyright (C) 2007 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.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ProviderInfo;
import android.content.res.Resources;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContext;
import android.test.mock.MockContentResolver;
import android.database.DatabaseUtils;

import java.io.File;

/**
 * This test case class provides a framework for testing a single
 * {@link ContentProvider} and for testing your app code with an
 * isolated content provider. Instead of using the system map of
 * providers that is based on the manifests of other applications, the test
 * case creates its own internal map. It then uses this map to resolve providers
 * given an authority. This allows you to inject test providers and to null out
 * providers that you do not want to use.
 * <p>
 *      This test case also sets up the following mock objects:
 * </p>
 * <ul>
 *      <li>
 *          An {@link android.test.IsolatedContext} that stubs out Context methods that might
 *          affect the rest of the running system, while allowing tests to do real file and
 *          database work.
 *      </li>
 *      <li>
 *          A {@link android.test.mock.MockContentResolver} that provides the functionality of a
 *          regular content resolver, but uses {@link IsolatedContext}. It stubs out
 *          {@link ContentResolver#notifyChange(Uri, ContentObserver, boolean)} to
 *          prevent the test from affecting the running system.
 *      </li>
 *      <li>
 *          An instance of the provider under test, running in an {@link IsolatedContext}.
 *      </li>
 * </ul>
 * <p>
 *      This framework is set up automatically by the base class' {@link #setUp()} method. If you
 *      override this method, you must call the super method as the first statement in
 *      your override.
 * </p>
 * <p>
 *     In order for their tests to be run, concrete subclasses must provide their own
 *     constructor with no arguments. This constructor must call
 *     {@link #ProviderTestCase2(Class, String)} as  its first operation.
 * </p>
 * For more information on content provider testing, please see
 * <a href="{@docRoot}tools/testing/contentprovider_testing.html">Content Provider Testing</a>.
 */
public abstract class ProviderTestCase2<T extends ContentProvider> extends AndroidTestCase {

    Class<T> mProviderClass;
    String mProviderAuthority;

    private IsolatedContext mProviderContext;
    private MockContentResolver mResolver;

    private class MockContext2 extends MockContext {

        @Override
        public Resources getResources() {
            return getContext().getResources();
        }

        @Override
        public File getDir(String name, int mode) {
            // name the directory so the directory will be separated from
            // one created through the regular Context
            return getContext().getDir("mockcontext2_" + name, mode);
        }

        @Override
        public Context getApplicationContext() {
            return this;
        }
    }
    /**
     * Constructor.
     *
     * @param providerClass The class name of the provider under test
     * @param providerAuthority The provider's authority string
     */
    public ProviderTestCase2(Class<T> providerClass, String providerAuthority) {
        mProviderClass = providerClass;
        mProviderAuthority = providerAuthority;
    }

    private T mProvider;

    /**
     * Returns the content provider created by this class in the {@link #setUp()} method.
     * @return T An instance of the provider class given as a parameter to the test case class.
     */
    public T getProvider() {
        return mProvider;
    }

    /**
     * Sets up the environment for the test fixture.
     * <p>
     * Creates a new
     * {@link android.test.mock.MockContentResolver}, a new IsolatedContext
     * that isolates the provider's file operations, and a new instance of
     * the provider under test within the isolated environment.
     * </p>
     *
     * @throws Exception
     */
    @Override
    protected void setUp() throws Exception {
        super.setUp();

        mResolver = new MockContentResolver();
        final String filenamePrefix = "test.";
        RenamingDelegatingContext targetContextWrapper = new
                RenamingDelegatingContext(
                new MockContext2(), // The context that most methods are
                                    //delegated to
                getContext(), // The context that file methods are delegated to
                filenamePrefix);
        mProviderContext = new IsolatedContext(mResolver, targetContextWrapper);
        mProvider = createProviderForTest(mProviderContext, mProviderClass, mProviderAuthority);
        mResolver.addProvider(mProviderAuthority, getProvider());
    }

    /**
     * Creates and sets up a new instance of the provider.
     */
    static <T extends ContentProvider> T createProviderForTest(
            Context context, Class<T> providerClass, String authority)
            throws IllegalAccessException, InstantiationException {
        T instance = providerClass.newInstance();
        ProviderInfo providerInfo = new ProviderInfo();
        providerInfo.authority = authority;
        MockContentProvider.attachInfoForTesting(instance, context, providerInfo);
        return instance;
    }

    /**
     * Tears down the environment for the test fixture.
     * <p>
     * Calls {@link android.content.ContentProvider#shutdown()} on the
     * {@link android.content.ContentProvider} represented by mProvider.
     */
    @Override
    protected void tearDown() throws Exception {
        mProvider.shutdown();
        super.tearDown();
    }

    /**
     * Gets the {@link MockContentResolver} created by this class during initialization. You
     * must use the methods of this resolver to access the provider under test.
     *
     * @return A {@link MockContentResolver} instance.
     */
    public MockContentResolver getMockContentResolver() {
        return mResolver;
    }

    /**
     * Gets the {@link IsolatedContext} created by this class during initialization.
     * @return The {@link IsolatedContext} instance
     */
    public IsolatedContext getMockContext() {
        return mProviderContext;
    }

    /**
     * <p>
     *      Creates a new content provider of the same type as that passed to the test case class,
     *      with an authority name set to the authority parameter, and using an SQLite database as
     *      the underlying data source. The SQL statement parameter is used to create the database.
     *      This method also creates a new {@link MockContentResolver} and adds the provider to it.
     * </p>
     * <p>
     *      Both the new provider and the new resolver are put into an {@link IsolatedContext}
     *      that uses the targetContext parameter for file operations and a {@link MockContext}
     *      for everything else. The IsolatedContext prepends the filenamePrefix parameter to
     *      file, database, and directory names.
     * </p>
     * <p>
     *      This is a convenience method for creating a "mock" provider that can contain test data.
     * </p>
     *
     * @param targetContext The context to use as the basis of the IsolatedContext
     * @param filenamePrefix A string that is prepended to file, database, and directory names
     * @param providerClass The type of the provider being tested
     * @param authority The authority string to associated with the test provider
     * @param databaseName The name assigned to the database
     * @param databaseVersion The version assigned to the database
     * @param sql A string containing the SQL statements that are needed to create the desired
     * database and its tables. The format is the same as that generated by the
     * <a href="http://www.sqlite.org/sqlite.html">sqlite3</a> tool's <code>.dump</code> command.
     * @return ContentResolver A new {@link MockContentResolver} linked to the provider
     *
     * @throws IllegalAccessException
     * @throws InstantiationException
     */
    public static <T extends ContentProvider> ContentResolver newResolverWithContentProviderFromSql(
            Context targetContext, String filenamePrefix, Class<T> providerClass, String authority,
            String databaseName, int databaseVersion, String sql)
            throws IllegalAccessException, InstantiationException {
        MockContentResolver resolver = new MockContentResolver();
        RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
                new MockContext(), // The context that most methods are delegated to
                targetContext, // The context that file methods are delegated to
                filenamePrefix);
        Context context = new IsolatedContext(resolver, targetContextWrapper);
        DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);

        T provider = createProviderForTest(context, providerClass, authority);
        resolver.addProvider(authority, provider);

        return resolver;
    }
}
