/*
 * Copyright (C) 2016 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.provider.cts;

import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.BlockedNumberContract;
import android.provider.BlockedNumberContract.BlockedNumbers;
import android.telephony.TelephonyManager;

import junit.framework.Assert;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * CTS tests for blockednumber provider accessed through {@link BlockedNumberContract}.
 */
// To run the tests in this file w/o running all the cts tests:
// make cts
// cts-tradefed
// run cts -m CtsProviderTestCases --test android.provider.cts.BlockedNumberContractTest
public class BlockedNumberContractTest extends TestCaseThatRunsIfTelephonyIsEnabled {
    private ContentResolver mContentResolver;
    private Context mContext;
    private ArrayList<Uri> mAddedUris;

    private static final String[] BLOCKED_NUMBERS_PROJECTION = new String[]{
            BlockedNumbers.COLUMN_ORIGINAL_NUMBER,
            BlockedNumbers.COLUMN_E164_NUMBER};

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContext = getInstrumentation().getContext();
        mContentResolver = mContext.getContentResolver();
        mAddedUris = new ArrayList<>();
    }

    @Override
    protected void tearDown() throws Exception {
        for (Uri row : mAddedUris) {
            mContentResolver.delete(row, null, null);
        }
        mAddedUris.clear();
        setDefaultSmsApp(false);

        super.tearDown();
    }

    public void testProviderInteractionsAsRegularApp_fails() {
        TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
        // Don't run this test if we're carrier privileged.
        if (telephonyManager.checkCarrierPrivilegesForPackage(mContext.getPackageName())
                == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
            return;
        }

        try {
            mAddedUris.add(mContentResolver.insert(
                    BlockedNumbers.CONTENT_URI, getContentValues("1234567890")));
            fail("Should throw SecurityException");
        } catch (SecurityException expected) {
        }

        try {
            mContentResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null);
            fail("Should throw SecurityException");
        } catch (SecurityException expected) {
        }

        try {
            mContentResolver.update(
                    BlockedNumbers.CONTENT_URI, getContentValues("123"), null, null);
            fail("Should throw SecurityException");
        } catch (SecurityException expected) {
        }

        try {
            BlockedNumberContract.isBlocked(mContext, "123");
            fail("Should throw SecurityException");
        } catch (SecurityException expected) {
        }

        try {
            BlockedNumberContract.unblock(mContext, "1234567890");
            fail("Should throw SecurityException");
        } catch (SecurityException expected) {
        }

        assertTrue(BlockedNumberContract.canCurrentUserBlockNumbers(mContext));
    }

    public void testGetType() throws Exception {
        assertEquals(BlockedNumbers.CONTENT_TYPE,
                mContentResolver.getType(BlockedNumbers.CONTENT_URI));
        assertEquals(BlockedNumbers.CONTENT_ITEM_TYPE,
                mContentResolver.getType(
                        ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, 0)));

        assertNull(mContentResolver.getType(BlockedNumberContract.AUTHORITY_URI));
    }

    public void testInsertAndBlockCheck_succeeds() throws Exception {
        setDefaultSmsApp(true);

        assertTrue(BlockedNumberContract.canCurrentUserBlockNumbers(mContext));

        assertInsertBlockedNumberSucceeds("1234567890", null);
        // Attempting to insert a duplicate replaces the existing entry.
        assertInsertBlockedNumberSucceeds("1234567890", "+812345678901");
        assertInsertBlockedNumberSucceeds("1234567890", null);

        assertTrue(BlockedNumberContract.isBlocked(mContext, "1234567890"));
        assertFalse(BlockedNumberContract.isBlocked(mContext, "2234567890"));

        assertInsertBlockedNumberSucceeds("2345678901", "+12345678901");
        assertTrue(BlockedNumberContract.isBlocked(mContext, "2345678901"));
        assertTrue(BlockedNumberContract.isBlocked(mContext, "+12345678901"));

        assertInsertBlockedNumberSucceeds("1234@abcd.com", null);
        assertTrue(BlockedNumberContract.isBlocked(mContext, "1234@abcd.com"));

        assertInsertBlockedNumberSucceeds("2345@abcd.com", null);
        assertTrue(BlockedNumberContract.isBlocked(mContext, "2345@abcd.com"));

        assertFalse(BlockedNumberContract.isBlocked(mContext, "9999@abcd.com"));
        assertFalse(BlockedNumberContract.isBlocked(mContext, "random string"));
    }

    public void testUnblock_succeeds() throws Exception {
        setDefaultSmsApp(true);

        // Unblocking non-existent blocked number should return 0.
        assertEquals(0, BlockedNumberContract.unblock(mContext, "6501004000"));

        assertInsertBlockedNumberSucceeds("6501004000", null);
        assertEquals(1, BlockedNumberContract.unblock(mContext, "6501004000"));
        assertFalse(BlockedNumberContract.isBlocked(mContext, "(650)1004000"));

        assertInsertBlockedNumberSucceeds("1234@abcd.com", null);
        assertEquals(1, BlockedNumberContract.unblock(mContext, "1234@abcd.com"));
        assertFalse(BlockedNumberContract.isBlocked(mContext, "1234@abcd.com"));
    }

    public void testInsert_failsWithInvalidInputs() throws Exception {
        setDefaultSmsApp(true);

        try {
            ContentValues cv = new ContentValues();
            cv.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, "1234");
            mAddedUris.add(mContentResolver.insert(
                    ContentUris.withAppendedId(BlockedNumbers.CONTENT_URI, 1),
                    new ContentValues()));
            fail("Should throw IllegalArgumentException.");
        } catch (IllegalArgumentException expected) {
            assertTrue(expected.getMessage().contains("Unsupported URI"));
        }

        try {
            mAddedUris.add(
                    mContentResolver.insert(BlockedNumbers.CONTENT_URI, new ContentValues()));
            fail("Should throw IllegalArgumentException.");
        } catch (IllegalArgumentException expected) {
            assertTrue(expected.getMessage().contains("Missing a required column"));
        }

        try {
            ContentValues cv = new ContentValues();
            cv.put(BlockedNumbers.COLUMN_E164_NUMBER, "+1234");
            mAddedUris.add(mContentResolver.insert(BlockedNumbers.CONTENT_URI, cv));
            fail("Should throw IllegalArgumentException.");
        } catch (IllegalArgumentException expected) {
            assertTrue(expected.getMessage().contains("Missing a required column"));
        }

        try {
            ContentValues cv = new ContentValues();
            cv.put(BlockedNumbers.COLUMN_ID, "1");
            mAddedUris.add(mContentResolver.insert(BlockedNumbers.CONTENT_URI, cv));
            fail("Should throw IllegalArgumentException.");
        } catch (IllegalArgumentException expected) {
            assertTrue(expected.getMessage().contains("must not be specified"));
        }
    }

    public void testUpdate_isUnsupported() throws  Exception {
        setDefaultSmsApp(true);
        try {
            mContentResolver.update(
                    BlockedNumbers.CONTENT_URI, getContentValues("123"), null, null);
            fail("Should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException expected) {
        }
    }

    public void testIsBlocked_returnsFalseForNullAndEmpty() throws Exception {
        setDefaultSmsApp(true);
        assertFalse(BlockedNumberContract.isBlocked(mContext, null));
        assertFalse(BlockedNumberContract.isBlocked(mContext, ""));
    }

    public void testDelete() throws Exception {
        setDefaultSmsApp(true);

        assertInsertBlockedNumberSucceeds("12345", "+112345");
        assertInsertBlockedNumberSucceeds("012345", "+112345");
        assertEquals(2,
                mContentResolver.delete(
                        BlockedNumbers.CONTENT_URI,
                        BlockedNumbers.COLUMN_E164_NUMBER + "= ?",
                        new String[] {"+112345"}));

        assertInsertBlockedNumberSucceeds("12345", "");
        assertEquals(1,
                mContentResolver.delete(
                        BlockedNumbers.CONTENT_URI,
                        BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?",
                        new String[] {"12345"}));

        Uri insertedUri = assertInsertBlockedNumberSucceeds("12345", "");
        assertEquals(1,
                mContentResolver.delete(
                        BlockedNumbers.CONTENT_URI,
                        BlockedNumbers.COLUMN_ID + "= ?",
                        new String[] {Long.toString(ContentUris.parseId(insertedUri))}));

        insertedUri = assertInsertBlockedNumberSucceeds("12345", "");
        assertEquals(1,
                mContentResolver.delete(
                        ContentUris.withAppendedId(
                                BlockedNumbers.CONTENT_URI, ContentUris.parseId(insertedUri)),
                        null, null));

        insertedUri = assertInsertBlockedNumberSucceeds("12345", "");
        assertEquals(1, mContentResolver.delete(insertedUri, null, null));

        assertEquals(0,
                mContentResolver.delete(
                        BlockedNumbers.CONTENT_URI,
                        BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?",
                        new String[] {"12345"}));
    }

    public void testDelete_failsOnInvalidInputs() throws Exception {
        setDefaultSmsApp(true);

        try {
            mContentResolver.delete(Uri.parse("foobar"), null, null);
            fail("Should throw IllegalArgumentException");
        } catch (IllegalArgumentException expected) {
        }

        Uri insertedUri = assertInsertBlockedNumberSucceeds("12345", "");
        try {
            mContentResolver.delete(
                    insertedUri,
                    BlockedNumbers.COLUMN_E164_NUMBER + "= ?",
                    new String[] {"+112345"});
            fail("Should throw IllegalArgumentException");
        } catch (IllegalArgumentException expected) {
            assertTrue(expected.getMessage().contains("selection must be null"));
        }
    }

    public void testProviderNotifiesChangesUsingContentObserver() throws Exception {
        setDefaultSmsApp(true);

        Cursor cursor = mContentResolver.query(BlockedNumbers.CONTENT_URI, null, null, null, null);

        final CountDownLatch latch = new CountDownLatch(2);
        ContentObserver contentObserver = new ContentObserver(null) {
            @Override
            public void onChange(boolean selfChange) {
                Assert.assertFalse(selfChange);
                latch.notify();
            }
        };
        cursor.registerContentObserver(contentObserver);

        try {
            Uri uri = assertInsertBlockedNumberSucceeds("12345", "");
            mContentResolver.delete(uri, null, null);
            latch.await(10, TimeUnit.SECONDS);
        } catch (Exception e) {
            fail(e.toString());
        } finally {
            cursor.unregisterContentObserver(contentObserver);
        }
    }

    public void testAccessingNonExistentMethod_fails() throws Exception {
        setDefaultSmsApp(true);

        try {
            mContext.getContentResolver()
                    .call(BlockedNumberContract.AUTHORITY_URI, "nonExistentMethod", "1234", null);
            fail("Should throw IllegalArgumentException");
        } catch (IllegalArgumentException expected) {
            assertTrue(expected.getMessage().contains("Unsupported method"));
        }
    }

    private Uri assertInsertBlockedNumberSucceeds(
            String originalNumber, @Nullable String e164Number) {
        ContentValues cv = new ContentValues();
        cv.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, originalNumber);
        if (e164Number != null) {
            cv.put(BlockedNumbers.COLUMN_E164_NUMBER, e164Number);
        }
        Uri insertedUri = mContentResolver.insert(BlockedNumbers.CONTENT_URI, cv);
        mAddedUris.add(insertedUri);

        Cursor cursor = mContentResolver.query(
                BlockedNumbers.CONTENT_URI,
                BLOCKED_NUMBERS_PROJECTION,
                BlockedNumbers.COLUMN_ORIGINAL_NUMBER + "= ?",
                new String[]{originalNumber},
                null);
        assertTrue(cursor.moveToFirst());

        assertEquals(originalNumber, cursor.getString(0));
        if (e164Number != null) {
            assertEquals(e164Number, cursor.getString(1));
        }
        cursor.close();
        return insertedUri;
    }

    private ContentValues getContentValues(String originalNumber) {
        ContentValues cv = new ContentValues();
        cv.put(BlockedNumbers.COLUMN_ORIGINAL_NUMBER, originalNumber);
        return cv;
    }

    private void setDefaultSmsApp(boolean setToSmsApp) throws Exception {
        ProviderTestUtils.setDefaultSmsApp(
                setToSmsApp, mContext.getPackageName(), getInstrumentation().getUiAutomation());
    }
}
