/*
 * Copyright (C) 2011 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 com.android.providers.contacts;

import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.os.BatteryStats.Uid.Proc;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.VoicemailContract;
import android.provider.VoicemailContract.Status;
import android.provider.VoicemailContract.Voicemails;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;

import com.android.common.io.MoreCloseables;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;

/**
 * Unit tests for {@link VoicemailContentProvider}.
 *
 * Run the test like this:
 * <code>
 * runtest -c com.android.providers.contacts.VoicemailProviderTest contactsprov
 * </code>
 */
// TODO: Test that calltype and voicemail_uri are auto populated by the provider.
@SmallTest
public class VoicemailProviderTest extends BaseVoicemailProviderTest {
    /** Fields specific to call_log provider that should not be exposed by voicemail provider. */
    private static final String[] CALLLOG_PROVIDER_SPECIFIC_COLUMNS = {
            Calls.CACHED_NAME,
            Calls.CACHED_NUMBER_LABEL,
            Calls.CACHED_NUMBER_TYPE,
            Calls.TYPE,
            Calls.VOICEMAIL_URI,
            Calls.COUNTRY_ISO
    };
    /** Total number of columns exposed by voicemail provider. */
    private static final int NUM_VOICEMAIL_FIELDS = 23;

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        setUpForOwnPermission();
        addProvider(CallLogProviderTestable.class, CallLog.AUTHORITY);
    }

    /** Returns the appropriate /voicemail URI. */
    private Uri voicemailUri() {
        return mUseSourceUri ?
                Voicemails.buildSourceUri(mActor.packageName) : Voicemails.CONTENT_URI;
    }

    /** Returns the appropriate /status URI. */
    private Uri statusUri() {
        return mUseSourceUri ?
                Status.buildSourceUri(mActor.packageName) : Status.CONTENT_URI;
    }

    public void testInsert() throws Exception {
        setTimeForTest(1000L);
        Uri uri = mResolver.insert(voicemailUri(), getTestVoicemailValues());
        // We create on purpose a new set of ContentValues here, because the code above modifies
        // the copy it gets.
        assertStoredValues(uri, getTestVoicemailValues());
        assertSelection(uri, getTestVoicemailValues(), Voicemails._ID, ContentUris.parseId(uri));
        assertEquals(1, countFilesInTestDirectory());

        assertLastModified(uri, 1000);
    }

    public void testInsertReadMessageIsNotNew() throws Exception {
        ContentValues values = getTestReadVoicemailValues();
        Uri uri = mResolver.insert(voicemailUri(), values);
        String[] projection = {Voicemails.NUMBER, Voicemails.DATE, Voicemails.DURATION,
                Voicemails.TRANSCRIPTION, Voicemails.IS_READ, Voicemails.HAS_CONTENT,
                Voicemails.SOURCE_DATA, Voicemails.STATE,
                Voicemails.BACKED_UP, Voicemails.RESTORED, Voicemails.ARCHIVED,
                Voicemails.IS_OMTP_VOICEMAIL
        };
        Cursor c = mResolver.query(uri, projection, Calls.NEW + "=0", null,
                null);
        try {
            assertEquals("Record count", 1, c.getCount());
            c.moveToFirst();
            assertEquals(1, countFilesInTestDirectory());
            assertCursorValues(c, values);
        } catch (Error e) {
            TestUtils.dumpCursor(c);
            throw e;
        } finally {
            c.close();
        }
    }

    // Test to ensure that media content can be written and read back.
    public void testFileContent() throws Exception {
        Uri uri = insertVoicemail();
        OutputStream out = mResolver.openOutputStream(uri);
        byte[] outBuffer = {0x1, 0x2, 0x3, 0x4};
        out.write(outBuffer);
        out.flush();
        out.close();
        InputStream in = mResolver.openInputStream(uri);
        byte[] inBuffer = new byte[4];
        int numBytesRead = in.read(inBuffer);
        assertEquals(numBytesRead, outBuffer.length);
        MoreAsserts.assertEquals(outBuffer, inBuffer);
        // No more data should be left.
        assertEquals(-1, in.read(inBuffer));
        in.close();
    }

    public void testUpdate() {
        setTimeForTest(1000L);
        Uri uri = insertVoicemail();
        ContentValues values = new ContentValues();
        values.put(Voicemails.NUMBER, "1-800-263-7643");
        values.put(Voicemails.DATE, 2000);
        values.put(Voicemails.DURATION, 40);
        values.put(Voicemails.TRANSCRIPTION, "Testing 123");
        values.put(Voicemails.STATE, 2);
        values.put(Voicemails.HAS_CONTENT, 1);
        values.put(Voicemails.SOURCE_DATA, "foo");
        values.put(Voicemails.PHONE_ACCOUNT_COMPONENT_NAME, "dummy_name");
        values.put(Voicemails.PHONE_ACCOUNT_ID, "dummy_account");
        values.put(Voicemails.BACKED_UP, 1);
        values.put(Voicemails.RESTORED, 1);
        values.put(Voicemails.ARCHIVED, 1);
        values.put(Voicemails.IS_OMTP_VOICEMAIL, 1);
        int count = mResolver.update(uri, values, null, null);
        assertEquals(1, count);
        assertStoredValues(uri, values);
        assertLastModified(uri, 1000);
    }

    public void testUpdateOwnPackageVoicemail_NotDirty() {
        final Uri uri = mResolver.insert(voicemailUri(), getTestVoicemailValues());
        mResolver.update(uri, new ContentValues(), null, null);

        // Updating a package's own voicemail should not make the voicemail dirty.
        ContentValues values = getTestVoicemailValues();
        values.put(Voicemails.DIRTY, "0");
        assertStoredValues(uri, values);
    }

    public void testUpdateOwnPackageVoicemail_RemovesDirtyStatus() {
        ContentValues values = getTestVoicemailValues();
        values.put(Voicemails.DIRTY, "1");
        final Uri uri = mResolver.insert(voicemailUri(), getTestVoicemailValues());

        mResolver.update(uri, new ContentValues(), null, null);
        // At this point, the voicemail should be set back to not dirty.
        ContentValues newValues = getTestVoicemailValues();
        newValues.put(Voicemails.DIRTY, "0");
        assertStoredValues(uri, newValues);
    }

    public void testDeleteOwnPackageVoicemail_DeletesRow() {
        setUpForFullPermission();
        final Uri ownVoicemail = insertVoicemail();
        assertEquals(1, getCount(voicemailUri(), null, null));

        mResolver.delete(ownVoicemail, null, null);

        assertEquals(0, getCount(ownVoicemail, null, null));
    }

    public void testDeleteOtherPackageVoicemail_SetsDirtyStatus() {
        setUpForFullPermission();
        setTimeForTest(1000L);
        final Uri anotherVoicemail = insertVoicemailForSourcePackage("another-package");
        assertEquals(1, getCount(voicemailUri(), null, null));

        // Clear the mapping for our own UID so that this doesn't look like an internal transaction.
        mPackageManager.removePackage(Process.myUid());
        mResolver.delete(anotherVoicemail, null, null);

        ContentValues values = getTestVoicemailValues();
        values.put(Voicemails.DIRTY, "1");
        values.put(Voicemails.DELETED, "1");

        assertEquals(1, getCount(anotherVoicemail, null, null));
        assertStoredValues(anotherVoicemail, values);
        assertLastModified(anotherVoicemail, 1000);
    }

    public void testDelete() {
        Uri uri = insertVoicemail();
        int count = mResolver.delete(voicemailUri(), Voicemails._ID + "="
                + ContentUris.parseId(uri), null);
        assertEquals(1, count);
        assertEquals(0, getCount(uri, null, null));
    }

    public void testUpdateAfterDelete_lastModifiedNotChanged() {
        setUpForFullPermission();
        setTimeForTest(1000L);
        final Uri anotherVoicemail = insertVoicemailForSourcePackage("another-package");
        assertEquals(1, getCount(voicemailUri(), null, null));

        // Clear the mapping for our own UID so that this doesn't look like an internal transaction.
        mPackageManager.removePackage(Process.myUid());
        mResolver.delete(anotherVoicemail, null, null);
        assertLastModified(anotherVoicemail, 1000);

        mPackageManager.addPackage(Process.myUid(), mActor.packageName);
        setTimeForTest(2000L);
        mResolver.update(anotherVoicemail, new ContentValues(), null, null);
        assertLastModified(anotherVoicemail, 1000);

        setTimeForTest(3000L);
        ContentValues values = new ContentValues();
        values.put(Voicemails.DELETED, "0");
        mResolver.update(anotherVoicemail, values, null, null);
        assertLastModified(anotherVoicemail, 3000);
    }

    public void testGetType_ItemUri() throws Exception {
        // Random item uri.
        assertEquals(Voicemails.ITEM_TYPE,
                mResolver.getType(ContentUris.withAppendedId(Voicemails.CONTENT_URI, 100)));
        // Item uri of an inserted voicemail.
        ContentValues values = getTestVoicemailValues();
        values.put(Voicemails.MIME_TYPE, "foo/bar");
        Uri uri = mResolver.insert(voicemailUri(), values);
        assertEquals(Voicemails.ITEM_TYPE, mResolver.getType(uri));
    }

    public void testGetType_DirUri() throws Exception {
        assertEquals(Voicemails.DIR_TYPE, mResolver.getType(Voicemails.CONTENT_URI));
        assertEquals(Voicemails.DIR_TYPE, mResolver.getType(Voicemails.buildSourceUri("foo")));
    }

    // Test to ensure that without full permission it is not possible to use the base uri (i.e. with
    // no package URI specified).
    public void testMustUsePackageUriWithoutFullPermission() {
        setUpForOwnPermission();
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.insert(Voicemails.CONTENT_URI, getTestVoicemailValues());
            }
        });

        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.update(Voicemails.CONTENT_URI, getTestVoicemailValues(), null, null);
            }
        });

        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.query(Voicemails.CONTENT_URI, null, null, null, null);
            }
        });

        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.delete(Voicemails.CONTENT_URI, null, null);
            }
        });
    }

    public void testPermissions_InsertAndQuery() {
        setUpForFullPermission();
        // Insert two records - one each with own and another package.
        insertVoicemail();
        insertVoicemailForSourcePackage("another-package");
        assertEquals(2, getCount(voicemailUri(), null, null));

        // Now give away full permission and check that only 1 message is accessible.
        setUpForOwnPermission();
        assertEquals(1, getCount(voicemailUri(), null, null));

        // Once again try to insert message for another package. This time
        // it should fail.
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                insertVoicemailForSourcePackage("another-package");
            }
        });

        setUpForNoPermission();
        mUseSourceUri = false;
        // With the READ_ALL_VOICEMAIL permission, we should now be able to read all voicemails
        mActor.addPermissions(READ_VOICEMAIL_PERMISSION);
        assertEquals(2, getCount(voicemailUri(), null, null));

        // An insert for another package should still fail
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                insertVoicemailForSourcePackage("another-package");
            }
        });
    }

    public void testPermissions_UpdateAndDelete() {
        setUpForFullPermission();
        // Insert two records - one each with own and another package.
        final Uri ownVoicemail = insertVoicemail();
        final Uri anotherVoicemail = insertVoicemailForSourcePackage("another-package");
        assertEquals(2, getCount(voicemailUri(), null, null));

        // Now give away full permission and check that we can update and delete only
        // the own voicemail.
        setUpForOwnPermission();
        mResolver.update(withSourcePackageParam(ownVoicemail),
                getTestVoicemailValues(), null, null);
        mResolver.delete(withSourcePackageParam(ownVoicemail), null, null);

        // However, attempting to update or delete another-package's voicemail should fail.
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.update(anotherVoicemail, null, null, null);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.delete(anotherVoicemail, null, null);
            }
        });

        // If we have the manage voicemail permission, we should be able to both update voicemails
        // from all packages.
        setUpForNoPermission();
        mActor.addPermissions(WRITE_VOICEMAIL_PERMISSION);
        mResolver.update(anotherVoicemail, getTestVoicemailValues(), null, null);

        // Now add the read voicemail permission temporarily to verify that the update actually
        // worked
        mActor.addPermissions(READ_VOICEMAIL_PERMISSION);
        assertStoredValues(anotherVoicemail, getTestVoicemailValues());
        mActor.removePermissions(READ_VOICEMAIL_PERMISSION);

        mResolver.delete(anotherVoicemail, null, null);

        // Now add the read voicemail permission temporarily to verify that the voicemail is
        // deleted.
        mActor.addPermissions(READ_VOICEMAIL_PERMISSION);

        assertEquals(0, getCount(anotherVoicemail, null, null));
    }

    private Uri withSourcePackageParam(Uri uri) {
        return uri.buildUpon()
            .appendQueryParameter(VoicemailContract.PARAM_KEY_SOURCE_PACKAGE, mActor.packageName)
            .build();
    }

    public void testUriPermissions() {
        setUpForFullPermission();
        final Uri uri1 = insertVoicemail();
        final Uri uri2 = insertVoicemail();
        // Give away all permissions before querying. Access to both uris should be denied.
        setUpForNoPermission();
        checkHasNoAccessToUri(uri1);
        checkHasNoAccessToUri(uri2);

        // Just grant permission to uri1. uri1 should pass but uri2 should still fail.
        mActor.addUriPermissions(uri1);
        checkHasReadOnlyAccessToUri(uri1);
        checkHasNoAccessToUri(uri2);

        // Cleanup.
        mActor.removeUriPermissions(uri1);
    }

    /*
     * Checks that the READ_ALL_VOICEMAIL permission provides read access to a uri.
     */
    public void testUriPermissions_ReadAccess() {
        setUpForFullPermission();
        final Uri uri1 = insertVoicemail();
        // Give away all permissions before querying. Access should be denied.
        setUpForNoPermission();
        mUseSourceUri = false;
        checkHasNoAccessToUri(uri1);

        mActor.addPermissions(READ_VOICEMAIL_PERMISSION);
        checkHasReadAccessToUri(uri1);
    }

    /*
     * Checks that the MANAGE_VOICEMAIL permission provides write access to a uri.
     */
    public void testUriPermissions_WriteAccess() {
        setUpForFullPermission();
        final Uri uri1 = insertVoicemail();
        // Give away all permissions before querying. Access should be denied.
        setUpForNoPermission();
        checkHasNoAccessToUri(uri1);

        mActor.addPermissions(WRITE_VOICEMAIL_PERMISSION);
        checkHasUpdateAndDeleteAccessToUri(uri1);
    }

    private void checkHasNoAccessToUri(final Uri uri) {
        checkHasNoReadAccessToUri(uri);
        checkHasNoWriteAccessToUri(uri);
    }

    private void checkHasReadOnlyAccessToUri(final Uri uri) {
        checkHasReadAccessToUri(uri);
        checkHasNoWriteAccessToUri(uri);
    }

    private void checkHasReadAccessToUri(final Uri uri) {
        Cursor cursor = null;
        try {
            cursor = mResolver.query(uri, null, null ,null, null);
            assertEquals(1, cursor.getCount());
            try {
                ParcelFileDescriptor fd = mResolver.openFileDescriptor(uri, "r");
                assertNotNull(fd);
                fd.close();
            } catch (FileNotFoundException e) {
                fail(e.getMessage());
            } catch (IOException e) {
                fail(e.getMessage());
            }
        } finally {
            MoreCloseables.closeQuietly(cursor);
        }
    }

    private void checkHasNoReadAccessToUri(final Uri uri) {
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.query(uri, null, null, null, null);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                try {
                    mResolver.openFileDescriptor(uri, "r");
                } catch (FileNotFoundException e) {
                    fail(e.getMessage());
                }
            }
        });
    }

    private void checkHasUpdateAndDeleteAccessToUri(final Uri uri) {
        mResolver.update(uri, getTestVoicemailValues(), null, null);
        mResolver.delete(uri, null, null);
    }

    private void checkHasNoWriteAccessToUri(final Uri uri) {
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.update(uri, getTestVoicemailValues(), null, null);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.delete(uri, null, null);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                try {
                    mResolver.openFileDescriptor(uri, "w");
                } catch (FileNotFoundException e) {
                    fail(e.getMessage());
                }
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                try {
                    mResolver.openFileDescriptor(uri, "rw");
                } catch (FileNotFoundException e) {
                    fail(e.getMessage());
                }
            }
        });
    }

    // Test to ensure that all operations fail when no voicemail permission is granted.
    public void testNoPermissions() {
        setUpForNoPermission();
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.insert(voicemailUri(), getTestVoicemailValues());
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.update(voicemailUri(), getTestVoicemailValues(), null, null);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.query(voicemailUri(), null, null, null, null);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.delete(voicemailUri(), null, null);
            }
        });
    }

    // Test to check that none of the call_log provider specific fields are
    // insertable through voicemail provider.
    public void testCannotAccessCallLogSpecificFields_Insert() {
        for (String callLogColumn : CALLLOG_PROVIDER_SPECIFIC_COLUMNS) {
            final ContentValues values = getTestVoicemailValues();
            values.put(callLogColumn, "foo");
            EvenMoreAsserts.assertThrows("Column: " + callLogColumn,
                    IllegalArgumentException.class, new Runnable() {
                    @Override
                    public void run() {
                        mResolver.insert(voicemailUri(), values);
                    }
                });
        }
    }

    // Test to check that none of the call_log provider specific fields are
    // exposed through voicemail provider query.
    public void testCannotAccessCallLogSpecificFields_Query() {
        // Query.
        Cursor cursor = mResolver.query(voicemailUri(), null, null, null, null);
        List<String> columnNames = Arrays.asList(cursor.getColumnNames());
        assertEquals(NUM_VOICEMAIL_FIELDS, columnNames.size());
        // None of the call_log provider specific columns should be present.
        for (String callLogColumn : CALLLOG_PROVIDER_SPECIFIC_COLUMNS) {
            assertFalse("Unexpected column: '" + callLogColumn + "' returned.",
                    columnNames.contains(callLogColumn));
        }
    }

    // Test to check that none of the call_log provider specific fields are
    // updatable through voicemail provider.
    public void testCannotAccessCallLogSpecificFields_Update() {
        for (String callLogColumn : CALLLOG_PROVIDER_SPECIFIC_COLUMNS) {
            final Uri insertedUri = insertVoicemail();
            final ContentValues values = getTestVoicemailValues();
            values.put(callLogColumn, "foo");
            EvenMoreAsserts.assertThrows("Column: " + callLogColumn,
                    IllegalArgumentException.class, new Runnable() {
                    @Override
                    public void run() {
                        mResolver.update(insertedUri, values, null, null);
                    }
                });
        }
    }

    // Tests for voicemail status table.

    public void testStatusInsert() throws Exception {
        ContentValues values = getTestStatusValues();
        Uri uri = mResolver.insert(statusUri(), values);
        assertStoredValues(uri, values);
        assertSelection(uri, values, Status._ID, ContentUris.parseId(uri));
    }

    public void testStatusUpdate() throws Exception {
        Uri uri = insertTestStatusEntry();
        ContentValues values = getTestStatusValues();
        values.put(Status.DATA_CHANNEL_STATE, Status.DATA_CHANNEL_STATE_NO_CONNECTION);
        values.put(Status.NOTIFICATION_CHANNEL_STATE,
                Status.NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING);
        values.put(Status.SOURCE_TYPE,
                "vvm_type_test2");
        int count = mResolver.update(uri, values, null, null);
        assertEquals(1, count);
        assertStoredValues(uri, values);
    }

    public void testStatusUpsert() throws Exception {
        ContentValues values = getTestStatusValues();
        mResolver.insert(statusUri(), values);
        ContentValues values2 = new ContentValues();
        values2.put(Status.CONFIGURATION_STATE, Status.CONFIGURATION_STATE_NOT_CONFIGURED);
        values.put(Status.CONFIGURATION_STATE, Status.CONFIGURATION_STATE_NOT_CONFIGURED);
        Uri uri = mResolver.insert(statusUri(), values2);
        assertStoredValues(uri, values);
        assertSelection(uri, values, Status._ID, ContentUris.parseId(uri));
    }

    public void testStatusDelete() {
        Uri uri = insertTestStatusEntry();
        int count = mResolver.delete(statusUri(), Status._ID + "="
                + ContentUris.parseId(uri), null);
        assertEquals(1, count);
        assertEquals(0, getCount(uri, null, null));
    }

    public void testStatusQuotaInsert() {
        ContentValues values = new ContentValues();
        values.put(Status.SOURCE_PACKAGE, mActor.packageName);
        values.put(Status.QUOTA_OCCUPIED, 2);
        values.put(Status.QUOTA_TOTAL, 13);
        Uri uri = mResolver.insert(statusUri(), values);
        assertStoredValues(uri, values);
        assertSelection(uri, values, Status._ID, ContentUris.parseId(uri));
    }

    public void testStatusQuotaUpdate() {
        Uri uri = insertTestStatusEntry();
        ContentValues values = new ContentValues();
        values.put(Status.SOURCE_PACKAGE, mActor.packageName);
        values.put(Status.QUOTA_OCCUPIED, 2);
        values.put(Status.QUOTA_TOTAL, 13);
        int count = mResolver.update(uri, values, null, null);
        assertEquals(1, count);

        ContentValues refValues = getTestStatusValues();
        refValues.put(Status.QUOTA_OCCUPIED, 2);
        refValues.put(Status.QUOTA_TOTAL, 13);
        assertStoredValues(uri, refValues);
    }

    public void testStatusQuotaUpsert() {
        Uri uri = insertTestStatusEntry();
        ContentValues values = new ContentValues();
        values.put(Status.SOURCE_PACKAGE, mActor.packageName);
        values.put(Status.QUOTA_OCCUPIED, 2);
        int count = mResolver.update(uri, values, null, null);

        ContentValues values2 = new ContentValues();
        values2.put(Status.QUOTA_TOTAL, 13);
        mResolver.insert(uri, values2);

        ContentValues refValues = getTestStatusValues();
        refValues.put(Status.QUOTA_OCCUPIED, 2);
        refValues.put(Status.QUOTA_TOTAL, 13);
        assertStoredValues(uri, refValues);
    }

    public void testStatusGetType() throws Exception {
        // Item URI.
        Uri uri = insertTestStatusEntry();
        assertEquals(Status.ITEM_TYPE, mResolver.getType(uri));

        // base URIs.
        assertEquals(Status.DIR_TYPE, mResolver.getType(Status.CONTENT_URI));
        assertEquals(Status.DIR_TYPE, mResolver.getType(Status.buildSourceUri("foo")));
    }

    // Basic permission checks for the status table.
    public void testStatusPermissions() throws Exception {
        final ContentValues values = getTestStatusValues();
        // Inserting for another package should fail with any of the URIs.
        values.put(Status.SOURCE_PACKAGE, "another.package");
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.insert(Status.CONTENT_URI, values);
            }
        });
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.insert(Status.buildSourceUri(mActor.packageName), values);
            }
        });

        // But insertion with own package should succeed with the right uri.
        values.put(Status.SOURCE_PACKAGE, mActor.packageName);
        final Uri uri = mResolver.insert(Status.buildSourceUri(mActor.packageName), values);
        assertNotNull(uri);

        // Updating source_package should not work as well.
        values.put(Status.SOURCE_PACKAGE, "another.package");
        EvenMoreAsserts.assertThrows(SecurityException.class, new Runnable() {
            @Override
            public void run() {
                mResolver.update(uri, values, null, null);
            }
        });
    }

    // File operation is not supported by /status URI.
    public void testStatusFileOperation() throws Exception {
        final Uri uri = insertTestStatusEntry();
        EvenMoreAsserts.assertThrows(UnsupportedOperationException.class, new Runnable() {
            @Override
            public void run() {
                try {
                    mResolver.openOutputStream(uri);
                } catch (FileNotFoundException e) {
                    fail("Unexpected exception " + e);
                }
            }
        });

        EvenMoreAsserts.assertThrows(UnsupportedOperationException.class, new Runnable() {
            @Override
            public void run() {
                try {
                    mResolver.openInputStream(uri);
                } catch (FileNotFoundException e) {
                    fail("Unexpected exception " + e);
                }
            }
        });
    }

    /**
     * Inserts a voicemail record with no source package set. The content provider
     * will detect source package.
     */
    private Uri insertVoicemail() {
        return mResolver.insert(voicemailUri(), getTestVoicemailValues());
    }

    /** Inserts a voicemail record for the specified source package. */
    private Uri insertVoicemailForSourcePackage(String sourcePackage) {
        ContentValues values = getTestVoicemailValues();
        values.put(Voicemails.SOURCE_PACKAGE, sourcePackage);
        return mResolver.insert(voicemailUri(), values);
    }

    private ContentValues getTestVoicemailValues() {
        ContentValues values = new ContentValues();
        values.put(Voicemails.NUMBER, "1-800-4664-411");
        values.put(Voicemails.DATE, 1000);
        values.put(Voicemails.DURATION, 30);
        values.put(Voicemails.TRANSCRIPTION, "Testing 123");
        values.put(Voicemails.IS_READ, 0);
        values.put(Voicemails.HAS_CONTENT, 0);
        values.put(Voicemails.SOURCE_DATA, "1234");
        values.put(Voicemails.STATE, Voicemails.STATE_INBOX);
        values.put(Voicemails.BACKED_UP, 0);
        values.put(Voicemails.RESTORED, 0);
        values.put(Voicemails.ARCHIVED, 0);
        values.put(Voicemails.IS_OMTP_VOICEMAIL, 0);
        return values;
    }

    private ContentValues getTestReadVoicemailValues() {
        ContentValues values = getTestVoicemailValues();
        values.put(Voicemails.IS_READ, 1);
        return values;
    }

    private Uri insertTestStatusEntry() {
        return mResolver.insert(statusUri(), getTestStatusValues());
    }

    private ContentValues getTestStatusValues() {
        ContentValues values = new ContentValues();
        values.put(Status.SOURCE_PACKAGE, mActor.packageName);
        values.put(Status.VOICEMAIL_ACCESS_URI, "tel:901");
        values.put(Status.SETTINGS_URI, "com.example.voicemail.source.SettingsActivity");
        values.put(Status.CONFIGURATION_STATE, Status.CONFIGURATION_STATE_OK);
        values.put(Status.DATA_CHANNEL_STATE, Status.DATA_CHANNEL_STATE_OK);
        values.put(Status.NOTIFICATION_CHANNEL_STATE, Status.NOTIFICATION_CHANNEL_STATE_OK);
        values.put(Status.SOURCE_TYPE, "vvm_type_test");
        return values;
    }

}
