15ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee/*
25ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Copyright (C) 2009 The Android Open Source Project
35ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
45ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Licensed under the Apache License, Version 2.0 (the "License");
55ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * you may not use this file except in compliance with the License.
65ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * You may obtain a copy of the License at
75ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
85ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *      http://www.apache.org/licenses/LICENSE-2.0
95ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee *
105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Unless required by applicable law or agreed to in writing, software
115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * distributed under the License is distributed on an "AS IS" BASIS,
125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * See the License for the specific language governing permissions and
145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * limitations under the License.
155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee */
165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leepackage com.android.contacts.common;
185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport static android.content.ContentProviderOperation.TYPE_ASSERT;
205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport static android.content.ContentProviderOperation.TYPE_DELETE;
215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport static android.content.ContentProviderOperation.TYPE_INSERT;
225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport static android.content.ContentProviderOperation.TYPE_UPDATE;
235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.ContentProviderOperation;
255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.ContentProviderOperation.Builder;
265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.ContentValues;
275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.content.Context;
285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.os.Parcel;
295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract.CommonDataKinds.Phone;
305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract.Data;
315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.provider.ContactsContract.RawContacts;
325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.test.AndroidTestCase;
335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport android.test.suitebuilder.annotation.LargeTest;
345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.android.contacts.common.model.RawContact;
365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.android.contacts.common.model.RawContactDelta;
375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.android.contacts.common.model.ValuesDelta;
385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport com.google.common.collect.Lists;
395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leeimport java.util.ArrayList;
415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee/**
435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * Tests for {@link RawContactDelta} and {@link ValuesDelta}. These tests
445ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * focus on passing changes across {@link Parcel}, and verifying that they
455ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee * correctly build expected "diff" operations.
465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee */
475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee@LargeTest
485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Leepublic class RawContactDeltaTests extends AndroidTestCase {
495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final String TAG = "EntityDeltaTests";
505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final long TEST_CONTACT_ID = 12;
525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final long TEST_PHONE_ID = 24;
535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final String TEST_PHONE_NUMBER_1 = "218-555-1111";
555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final String TEST_PHONE_NUMBER_2 = "218-555-2222";
565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static final String TEST_ACCOUNT_NAME = "TEST";
585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public RawContactDeltaTests() {
605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        super();
615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    @Override
645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void setUp() {
655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        mContext = getContext();
665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public static RawContact getRawContact(Context context, long contactId, long phoneId) {
695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Build an existing contact read from database
705ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues contact = new ContentValues();
715ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        contact.put(RawContacts.VERSION, 43);
725ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        contact.put(RawContacts._ID, contactId);
735ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
745ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues phone = new ContentValues();
755ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Data._ID, phoneId);
765ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
775ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_1);
785ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.TYPE, Phone.TYPE_HOME);
795ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
805ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = new RawContact(contact);
815ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        before.addDataItemValues(phone);
825ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        return before;
835ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
845ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
855ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
865ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Test that {@link RawContactDelta#mergeAfter(RawContactDelta)} correctly passes
875ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * any changes through the {@link Parcel} object. This enforces that
885ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * {@link RawContactDelta} should be identical when serialized against the same
895ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * "before" {@link RawContact}.
905ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
915ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testParcelChangesNone() {
925ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
935ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
945ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta dest = RawContactDelta.fromBefore(before);
955ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
965ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Merge modified values and assert they match
975ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
985ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected change when merging", source, merged);
995ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1005ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1015ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testParcelChangesInsert() {
1025ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
1035ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
1045ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta dest = RawContactDelta.fromBefore(before);
1055ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1065ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Add a new row and pass across parcel, should be same
1075ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues phone = new ContentValues();
1085ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
1095ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
1105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.TYPE, Phone.TYPE_WORK);
1115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.addEntry(ValuesDelta.fromAfter(phone));
1125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Merge modified values and assert they match
1145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
1155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected change when merging", source, merged);
1165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testParcelChangesUpdate() {
1195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Update existing row and pass across parcel, should be same
1205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
1215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
1225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta dest = RawContactDelta.fromBefore(before);
1235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ValuesDelta child = source.getEntry(TEST_PHONE_ID);
1255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        child.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
1265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Merge modified values and assert they match
1285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
1295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected change when merging", source, merged);
1305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testParcelChangesDelete() {
1335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Delete a row and pass across parcel, should be same
1345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
1355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
1365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta dest = RawContactDelta.fromBefore(before);
1375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ValuesDelta child = source.getEntry(TEST_PHONE_ID);
1395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        child.markDeleted();
1405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Merge modified values and assert they match
1425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta merged = RawContactDelta.mergeAfter(dest, source);
1435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected change when merging", source, merged);
1445ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1455ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testValuesDiffDelete() {
1475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues before = new ContentValues();
1485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        before.put(Data._ID, TEST_PHONE_ID);
1495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        before.put(Phone.NUMBER, TEST_PHONE_NUMBER_1);
1505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ValuesDelta values = ValuesDelta.fromBefore(before);
1525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        values.markDeleted();
1535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Should produce a delete action
1555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final Builder builder = values.buildDiff(Data.CONTENT_URI);
1565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final int type = builder.build().getType();
1575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Didn't produce delete action", TYPE_DELETE, type);
1585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    /**
1615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * Test that {@link RawContactDelta#buildDiff(ArrayList)} is correctly built for
1625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * insert, update, and delete cases. This only tests a subset of possible
1635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     * {@link Data} row changes.
1645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee     */
1655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffNone() {
1665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
1675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
1685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert that writing unchanged produces few operations
1705ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
1715ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
1725ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1735ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertTrue("Created changes when none needed", (diff.size() == 0));
1745ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
1755ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1765ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffNoneInsert() {
1775ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
1785ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
1795ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1805ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Insert a new phone number
1815ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues phone = new ContentValues();
1825ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
1835ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
1845ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.TYPE, Phone.TYPE_WORK);
1855ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.addEntry(ValuesDelta.fromAfter(phone));
1865ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
1875ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert two operations: insert Data row and enforce version
1885ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
1895ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildAssert(diff);
1905ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
1915ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected operations", 4, diff.size());
1925ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
1935ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(0);
1945ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
1955ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
1965ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
1975ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(1);
1985ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
1995ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2005ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2015ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2025ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(2);
2035ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
2045ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
2055ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2065ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2075ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(3);
2085ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
2095ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
2125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffUpdateInsert() {
2145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
2155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
2165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Update parent contact values
2185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.getValues().put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_DISABLED);
2195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Insert a new phone number
2215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues phone = new ContentValues();
2225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
2235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
2245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.TYPE, Phone.TYPE_WORK);
2255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.addEntry(ValuesDelta.fromAfter(phone));
2265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert three operations: update Contact, insert Data row, enforce version
2285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
2295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildAssert(diff);
2305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
2315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected operations", 5, diff.size());
2325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(0);
2345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
2355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(1);
2385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
2395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(2);
2435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
2445ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2455ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(3);
2485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
2495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
2505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(4);
2535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
2545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
2575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffNoneUpdate() {
2595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
2605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
2615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Update existing phone number
2635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ValuesDelta child = source.getEntry(TEST_PHONE_ID);
2645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        child.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
2655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert that version is enforced
2675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
2685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildAssert(diff);
2695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
2705ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected operations", 4, diff.size());
2715ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2725ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(0);
2735ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
2745ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2755ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2765ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(1);
2775ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
2785ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2795ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2805ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2815ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(2);
2825ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
2835ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
2845ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2855ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
2865ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(3);
2875ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
2885ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
2895ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
2905ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
2915ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2925ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffDelete() {
2935ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContact before = getRawContact(mContext, TEST_CONTACT_ID, TEST_PHONE_ID);
2945ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = RawContactDelta.fromBefore(before);
2955ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2965ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Delete entire entity
2975ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.getValues().markDeleted();
2985ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
2995ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert two operations: delete Contact and enforce version
3005ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
3015ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildAssert(diff);
3025ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
3035ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected operations", 2, diff.size());
3045ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
3055ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(0);
3065ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Expected version enforcement", TYPE_ASSERT, oper.getType());
3075ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
3085ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
3095ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(1);
3105ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
3115ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3125ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
3135ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
3145ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3155ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffInsert() {
3165ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Insert a RawContact
3175ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues after = new ContentValues();
3185ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        after.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
3195ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
3205ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3215ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ValuesDelta values = ValuesDelta.fromAfter(after);
3225ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = new RawContactDelta(values);
3235ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3245ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert two operations: delete Contact and enforce version
3255ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
3265ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildAssert(diff);
3275ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
3285ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected operations", 2, diff.size());
3295ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
3305ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(0);
3315ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
3325ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3335ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
3345ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
3355ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3365ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    public void testEntityDiffInsertInsert() {
3375ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Insert a RawContact
3385ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues after = new ContentValues();
3395ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        after.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
3405ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        after.put(RawContacts.SEND_TO_VOICEMAIL, 1);
3415ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3425ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ValuesDelta values = ValuesDelta.fromAfter(after);
3435ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final RawContactDelta source = new RawContactDelta(values);
3445ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3455ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Insert a new phone number
3465ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ContentValues phone = new ContentValues();
3475ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
3485ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.NUMBER, TEST_PHONE_NUMBER_2);
3495ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        phone.put(Phone.TYPE, Phone.TYPE_WORK);
3505ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.addEntry(ValuesDelta.fromAfter(phone));
3515ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3525ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        // Assert two operations: delete Contact and enforce version
3535ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
3545ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildAssert(diff);
3555ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        source.buildDiff(diff);
3565ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        assertEquals("Unexpected operations", 3, diff.size());
3575ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
3585ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(0);
3595ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
3605ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3615ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
3625ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        {
3635ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            final ContentProviderOperation oper = diff.get(1);
3645ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
3655ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
3665ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee
3675ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee        }
3685ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee    }
3695ade0bb1757b216ace2f50d2357409bf9876a07aYorke Lee}
370