12644d947574240b71c427d457f7a775dc160ec09Yorke Lee/* 22644d947574240b71c427d457f7a775dc160ec09Yorke Lee * Copyright (C) 2009 The Android Open Source Project 32644d947574240b71c427d457f7a775dc160ec09Yorke Lee * 42644d947574240b71c427d457f7a775dc160ec09Yorke Lee * Licensed under the Apache License, Version 2.0 (the "License"); 52644d947574240b71c427d457f7a775dc160ec09Yorke Lee * you may not use this file except in compliance with the License. 62644d947574240b71c427d457f7a775dc160ec09Yorke Lee * You may obtain a copy of the License at 72644d947574240b71c427d457f7a775dc160ec09Yorke Lee * 82644d947574240b71c427d457f7a775dc160ec09Yorke Lee * http://www.apache.org/licenses/LICENSE-2.0 92644d947574240b71c427d457f7a775dc160ec09Yorke Lee * 102644d947574240b71c427d457f7a775dc160ec09Yorke Lee * Unless required by applicable law or agreed to in writing, software 112644d947574240b71c427d457f7a775dc160ec09Yorke Lee * distributed under the License is distributed on an "AS IS" BASIS, 122644d947574240b71c427d457f7a775dc160ec09Yorke Lee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132644d947574240b71c427d457f7a775dc160ec09Yorke Lee * See the License for the specific language governing permissions and 142644d947574240b71c427d457f7a775dc160ec09Yorke Lee * limitations under the License. 152644d947574240b71c427d457f7a775dc160ec09Yorke Lee */ 162644d947574240b71c427d457f7a775dc160ec09Yorke Lee 170a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maipackage com.android.contacts.model; 182644d947574240b71c427d457f7a775dc160ec09Yorke Lee 192644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.content.ContentProviderOperation; 202644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.content.ContentValues; 212644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.content.Context; 222644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.net.Uri; 232644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.provider.BaseColumns; 242644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.provider.ContactsContract.AggregationExceptions; 252644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.provider.ContactsContract.CommonDataKinds.Email; 262644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.provider.ContactsContract.CommonDataKinds.Phone; 272644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.provider.ContactsContract.Data; 282644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.provider.ContactsContract.RawContacts; 292644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.test.AndroidTestCase; 302644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport android.test.suitebuilder.annotation.LargeTest; 312644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3269c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.compat.CompatUtils; 3369c182afb0e6d82a341a28b4317aa703af768906Gary Maiimport com.android.contacts.model.account.AccountType; 342644d947574240b71c427d457f7a775dc160ec09Yorke Lee 350a49afa2ad697307cc04ef4cb86570574fa720f2Gary Maiimport com.google.common.collect.Lists; 362644d947574240b71c427d457f7a775dc160ec09Yorke Lee 372644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport java.lang.reflect.Field; 382644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport java.util.ArrayList; 392644d947574240b71c427d457f7a775dc160ec09Yorke Leeimport java.util.Collections; 402644d947574240b71c427d457f7a775dc160ec09Yorke Lee 412644d947574240b71c427d457f7a775dc160ec09Yorke Lee/** 422644d947574240b71c427d457f7a775dc160ec09Yorke Lee * Tests for {@link RawContactDeltaList} which focus on "diff" operations that should 432644d947574240b71c427d457f7a775dc160ec09Yorke Lee * create {@link AggregationExceptions} in certain cases. 442644d947574240b71c427d457f7a775dc160ec09Yorke Lee */ 452644d947574240b71c427d457f7a775dc160ec09Yorke Lee@LargeTest 462644d947574240b71c427d457f7a775dc160ec09Yorke Leepublic class RawContactDeltaListTests extends AndroidTestCase { 477bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner // From android.content.ContentProviderOperation 487bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner public static final int TYPE_INSERT = 1; 497bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner public static final int TYPE_UPDATE = 2; 507bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner public static final int TYPE_DELETE = 3; 517bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner public static final int TYPE_ASSERT = 4; 527bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner 532644d947574240b71c427d457f7a775dc160ec09Yorke Lee private static final long CONTACT_FIRST = 1; 542644d947574240b71c427d457f7a775dc160ec09Yorke Lee private static final long CONTACT_SECOND = 2; 552644d947574240b71c427d457f7a775dc160ec09Yorke Lee 562644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long CONTACT_BOB = 10; 572644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long CONTACT_MARY = 11; 582644d947574240b71c427d457f7a775dc160ec09Yorke Lee 592644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long PHONE_RED = 20; 602644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long PHONE_GREEN = 21; 612644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long PHONE_BLUE = 22; 622644d947574240b71c427d457f7a775dc160ec09Yorke Lee 632644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long EMAIL_YELLOW = 25; 642644d947574240b71c427d457f7a775dc160ec09Yorke Lee 652644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long VER_FIRST = 100; 662644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final long VER_SECOND = 200; 672644d947574240b71c427d457f7a775dc160ec09Yorke Lee 682644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final String TEST_PHONE = "555-1212"; 692644d947574240b71c427d457f7a775dc160ec09Yorke Lee public static final String TEST_ACCOUNT = "org.example.test"; 702644d947574240b71c427d457f7a775dc160ec09Yorke Lee 712644d947574240b71c427d457f7a775dc160ec09Yorke Lee public RawContactDeltaListTests() { 722644d947574240b71c427d457f7a775dc160ec09Yorke Lee super(); 732644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 742644d947574240b71c427d457f7a775dc160ec09Yorke Lee 752644d947574240b71c427d457f7a775dc160ec09Yorke Lee @Override 762644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void setUp() { 772644d947574240b71c427d457f7a775dc160ec09Yorke Lee mContext = getContext(); 782644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 792644d947574240b71c427d457f7a775dc160ec09Yorke Lee 802644d947574240b71c427d457f7a775dc160ec09Yorke Lee /** 812644d947574240b71c427d457f7a775dc160ec09Yorke Lee * Build a {@link AccountType} that has various odd constraints for 822644d947574240b71c427d457f7a775dc160ec09Yorke Lee * testing purposes. 832644d947574240b71c427d457f7a775dc160ec09Yorke Lee */ 842644d947574240b71c427d457f7a775dc160ec09Yorke Lee protected AccountType getAccountType() { 850a49afa2ad697307cc04ef4cb86570574fa720f2Gary Mai return new RawContactModifierTests.MockContactsSource(); 862644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 872644d947574240b71c427d457f7a775dc160ec09Yorke Lee 882644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentValues getValues(ContentProviderOperation operation) 892644d947574240b71c427d457f7a775dc160ec09Yorke Lee throws NoSuchFieldException, IllegalAccessException { 902644d947574240b71c427d457f7a775dc160ec09Yorke Lee final Field field = ContentProviderOperation.class.getDeclaredField("mValues"); 912644d947574240b71c427d457f7a775dc160ec09Yorke Lee field.setAccessible(true); 922644d947574240b71c427d457f7a775dc160ec09Yorke Lee return (ContentValues) field.get(operation); 932644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 942644d947574240b71c427d457f7a775dc160ec09Yorke Lee 952644d947574240b71c427d457f7a775dc160ec09Yorke Lee static RawContactDelta getUpdate(Context context, long rawContactId) { 962644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContact before = RawContactDeltaTests.getRawContact(context, rawContactId, 972644d947574240b71c427d457f7a775dc160ec09Yorke Lee RawContactDeltaTests.TEST_PHONE_ID); 982644d947574240b71c427d457f7a775dc160ec09Yorke Lee return RawContactDelta.fromBefore(before); 992644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1002644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1012644d947574240b71c427d457f7a775dc160ec09Yorke Lee static RawContactDelta getInsert() { 1022644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues after = new ContentValues(); 1032644d947574240b71c427d457f7a775dc160ec09Yorke Lee after.put(RawContacts.ACCOUNT_NAME, RawContactDeltaTests.TEST_ACCOUNT_NAME); 1042644d947574240b71c427d457f7a775dc160ec09Yorke Lee after.put(RawContacts.SEND_TO_VOICEMAIL, 1); 1052644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1062644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta values = ValuesDelta.fromAfter(after); 1072644d947574240b71c427d457f7a775dc160ec09Yorke Lee return new RawContactDelta(values); 1082644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1092644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1102644d947574240b71c427d457f7a775dc160ec09Yorke Lee static RawContactDeltaList buildSet(RawContactDelta... deltas) { 1112644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList set = new RawContactDeltaList(); 1122644d947574240b71c427d457f7a775dc160ec09Yorke Lee Collections.addAll(set, deltas); 1132644d947574240b71c427d457f7a775dc160ec09Yorke Lee return set; 1142644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1152644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1162644d947574240b71c427d457f7a775dc160ec09Yorke Lee static RawContactDelta buildBeforeEntity(Context context, long rawContactId, long version, 1172644d947574240b71c427d457f7a775dc160ec09Yorke Lee ContentValues... entries) { 1182644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Build an existing contact read from database 1192644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues contact = new ContentValues(); 1202644d947574240b71c427d457f7a775dc160ec09Yorke Lee contact.put(RawContacts.VERSION, version); 1212644d947574240b71c427d457f7a775dc160ec09Yorke Lee contact.put(RawContacts._ID, rawContactId); 1222644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContact before = new RawContact(contact); 1232644d947574240b71c427d457f7a775dc160ec09Yorke Lee for (ContentValues entry : entries) { 1242644d947574240b71c427d457f7a775dc160ec09Yorke Lee before.addDataItemValues(entry); 1252644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1262644d947574240b71c427d457f7a775dc160ec09Yorke Lee return RawContactDelta.fromBefore(before); 1272644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1282644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1292644d947574240b71c427d457f7a775dc160ec09Yorke Lee static RawContactDelta buildAfterEntity(ContentValues... entries) { 1302644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Build an existing contact read from database 1312644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues contact = new ContentValues(); 1322644d947574240b71c427d457f7a775dc160ec09Yorke Lee contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT); 1332644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta after = new RawContactDelta(ValuesDelta.fromAfter(contact)); 1342644d947574240b71c427d457f7a775dc160ec09Yorke Lee for (ContentValues entry : entries) { 1352644d947574240b71c427d457f7a775dc160ec09Yorke Lee after.addEntry(ValuesDelta.fromAfter(entry)); 1362644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1372644d947574240b71c427d457f7a775dc160ec09Yorke Lee return after; 1382644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1392644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1402644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentValues buildPhone(long phoneId) { 1412644d947574240b71c427d457f7a775dc160ec09Yorke Lee return buildPhone(phoneId, Long.toString(phoneId)); 1422644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1432644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1442644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentValues buildPhone(long phoneId, String value) { 1452644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues values = new ContentValues(); 1462644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Data._ID, phoneId); 1472644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); 1482644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Phone.NUMBER, value); 1492644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Phone.TYPE, Phone.TYPE_HOME); 1502644d947574240b71c427d457f7a775dc160ec09Yorke Lee return values; 1512644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1522644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1532644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentValues buildEmail(long emailId) { 1542644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues values = new ContentValues(); 1552644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Data._ID, emailId); 1562644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); 1572644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Email.DATA, Long.toString(emailId)); 1582644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(Email.TYPE, Email.TYPE_HOME); 1592644d947574240b71c427d457f7a775dc160ec09Yorke Lee return values; 1602644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1612644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1622644d947574240b71c427d457f7a775dc160ec09Yorke Lee static void insertPhone(RawContactDeltaList set, long rawContactId, ContentValues values) { 1632644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta match = set.getByRawContactId(rawContactId); 1642644d947574240b71c427d457f7a775dc160ec09Yorke Lee match.addEntry(ValuesDelta.fromAfter(values)); 1652644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1662644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1672644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ValuesDelta getPhone(RawContactDeltaList set, long rawContactId, long dataId) { 1682644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta match = set.getByRawContactId(rawContactId); 1692644d947574240b71c427d457f7a775dc160ec09Yorke Lee return match.getEntry(dataId); 1702644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1712644d947574240b71c427d457f7a775dc160ec09Yorke Lee 172009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static void assertDiffPattern(RawContactDelta delta, CPOWrapper... pattern) { 173009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang final ArrayList<CPOWrapper> diff = Lists.newArrayList(); 174009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang delta.buildAssertWrapper(diff); 175009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang delta.buildDiffWrapper(diff); 1762644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(diff, pattern); 1772644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1782644d947574240b71c427d457f7a775dc160ec09Yorke Lee 179009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static void assertDiffPattern(RawContactDeltaList set, CPOWrapper... pattern) { 180009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang assertDiffPattern(set.buildDiffWrapper(), pattern); 1812644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 1822644d947574240b71c427d457f7a775dc160ec09Yorke Lee 183009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static void assertDiffPattern(ArrayList<CPOWrapper> diff, CPOWrapper... pattern) { 1842644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected operations", pattern.length, diff.size()); 1852644d947574240b71c427d457f7a775dc160ec09Yorke Lee for (int i = 0; i < pattern.length; i++) { 186009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang final CPOWrapper expected = pattern[i]; 187009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang final CPOWrapper found = diff.get(i); 1882644d947574240b71c427d457f7a775dc160ec09Yorke Lee 189009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang assertEquals("Unexpected uri", 190009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang expected.getOperation().getUri(), found.getOperation().getUri()); 1912644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1927bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner final String expectedType = getTypeString(expected); 1937bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner final String foundType = getTypeString(found); 1942644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected type", expectedType, foundType); 1952644d947574240b71c427d457f7a775dc160ec09Yorke Lee 196009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang if (CompatUtils.isDeleteCompat(expected)) continue; 1972644d947574240b71c427d457f7a775dc160ec09Yorke Lee 1982644d947574240b71c427d457f7a775dc160ec09Yorke Lee try { 199009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang final ContentValues expectedValues = getValues(expected.getOperation()); 200009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang final ContentValues foundValues = getValues(found.getOperation()); 2012644d947574240b71c427d457f7a775dc160ec09Yorke Lee 2022644d947574240b71c427d457f7a775dc160ec09Yorke Lee expectedValues.remove(BaseColumns._ID); 2032644d947574240b71c427d457f7a775dc160ec09Yorke Lee foundValues.remove(BaseColumns._ID); 2042644d947574240b71c427d457f7a775dc160ec09Yorke Lee 2052644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected values", expectedValues, foundValues); 2062644d947574240b71c427d457f7a775dc160ec09Yorke Lee } catch (NoSuchFieldException e) { 2072644d947574240b71c427d457f7a775dc160ec09Yorke Lee fail(e.toString()); 2082644d947574240b71c427d457f7a775dc160ec09Yorke Lee } catch (IllegalAccessException e) { 2092644d947574240b71c427d457f7a775dc160ec09Yorke Lee fail(e.toString()); 2102644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2112644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2122644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2132644d947574240b71c427d457f7a775dc160ec09Yorke Lee 214009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static String getTypeString(CPOWrapper cpoWrapper) { 215009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang if (CompatUtils.isAssertQueryCompat(cpoWrapper)) { 2167bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner return "TYPE_ASSERT"; 217009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang } else if (CompatUtils.isInsertCompat(cpoWrapper)) { 2187bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner return "TYPE_INSERT"; 219009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang } else if (CompatUtils.isUpdateCompat(cpoWrapper)) { 2207bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner return "TYPE_UPDATE"; 221009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang } else if (CompatUtils.isDeleteCompat(cpoWrapper)) { 2227bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner return "TYPE_DELETE"; 2232644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2247bae063fae6b355fce1f91d342314f4d4798b30aJay Shrauner return "TYPE_UNKNOWN"; 2252644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2262644d947574240b71c427d457f7a775dc160ec09Yorke Lee 227009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildAssertVersion(long version) { 2282644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues values = new ContentValues(); 2292644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(RawContacts.VERSION, version); 230009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang return buildCPOWrapper(RawContacts.CONTENT_URI, TYPE_ASSERT, values); 2312644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2322644d947574240b71c427d457f7a775dc160ec09Yorke Lee 233009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildAggregationModeUpdate(int mode) { 2342644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues values = new ContentValues(); 2352644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(RawContacts.AGGREGATION_MODE, mode); 236009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang return buildCPOWrapper(RawContacts.CONTENT_URI, TYPE_UPDATE, values); 2372644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2382644d947574240b71c427d457f7a775dc160ec09Yorke Lee 239009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildUpdateAggregationSuspended() { 2402644d947574240b71c427d457f7a775dc160ec09Yorke Lee return buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_SUSPENDED); 2412644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2422644d947574240b71c427d457f7a775dc160ec09Yorke Lee 243009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildUpdateAggregationDefault() { 2442644d947574240b71c427d457f7a775dc160ec09Yorke Lee return buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT); 2452644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2462644d947574240b71c427d457f7a775dc160ec09Yorke Lee 247009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildUpdateAggregationKeepTogether(long rawContactId) { 2482644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues values = new ContentValues(); 2492644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(AggregationExceptions.RAW_CONTACT_ID1, rawContactId); 2502644d947574240b71c427d457f7a775dc160ec09Yorke Lee values.put(AggregationExceptions.TYPE, AggregationExceptions.TYPE_KEEP_TOGETHER); 251009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang return buildCPOWrapper(AggregationExceptions.CONTENT_URI, TYPE_UPDATE, values); 2522644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2532644d947574240b71c427d457f7a775dc160ec09Yorke Lee 2542644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentValues buildDataInsert(ValuesDelta values, long rawContactId) { 2552644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues insertValues = values.getCompleteValues(); 2562644d947574240b71c427d457f7a775dc160ec09Yorke Lee insertValues.put(Data.RAW_CONTACT_ID, rawContactId); 2572644d947574240b71c427d457f7a775dc160ec09Yorke Lee return insertValues; 2582644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2592644d947574240b71c427d457f7a775dc160ec09Yorke Lee 260009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildDelete(Uri uri) { 261009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang return buildCPOWrapper(uri, TYPE_DELETE, (ContentValues) null); 2622644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2632644d947574240b71c427d457f7a775dc160ec09Yorke Lee 2642644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentProviderOperation buildOper(Uri uri, int type, ValuesDelta values) { 2652644d947574240b71c427d457f7a775dc160ec09Yorke Lee return buildOper(uri, type, values.getCompleteValues()); 2662644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2672644d947574240b71c427d457f7a775dc160ec09Yorke Lee 2682644d947574240b71c427d457f7a775dc160ec09Yorke Lee static ContentProviderOperation buildOper(Uri uri, int type, ContentValues values) { 2692644d947574240b71c427d457f7a775dc160ec09Yorke Lee switch (type) { 2702644d947574240b71c427d457f7a775dc160ec09Yorke Lee case TYPE_ASSERT: 2712644d947574240b71c427d457f7a775dc160ec09Yorke Lee return ContentProviderOperation.newAssertQuery(uri).withValues(values).build(); 2722644d947574240b71c427d457f7a775dc160ec09Yorke Lee case TYPE_INSERT: 2732644d947574240b71c427d457f7a775dc160ec09Yorke Lee return ContentProviderOperation.newInsert(uri).withValues(values).build(); 2742644d947574240b71c427d457f7a775dc160ec09Yorke Lee case TYPE_UPDATE: 2752644d947574240b71c427d457f7a775dc160ec09Yorke Lee return ContentProviderOperation.newUpdate(uri).withValues(values).build(); 2762644d947574240b71c427d457f7a775dc160ec09Yorke Lee case TYPE_DELETE: 2772644d947574240b71c427d457f7a775dc160ec09Yorke Lee return ContentProviderOperation.newDelete(uri).build(); 2782644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2792644d947574240b71c427d457f7a775dc160ec09Yorke Lee return null; 2802644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2812644d947574240b71c427d457f7a775dc160ec09Yorke Lee 282009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang static CPOWrapper buildCPOWrapper(Uri uri, int type, ContentValues values) { 283009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang if (type == TYPE_ASSERT || type == TYPE_INSERT || type == TYPE_UPDATE 284009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang || type == TYPE_DELETE) { 285009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang return new CPOWrapper(buildOper(uri, type, values), type); 286009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang } 287009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang return null; 288009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang } 289009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang 2902644d947574240b71c427d457f7a775dc160ec09Yorke Lee static Long getVersion(RawContactDeltaList set, Long rawContactId) { 2912644d947574240b71c427d457f7a775dc160ec09Yorke Lee return set.getByRawContactId(rawContactId).getValues().getAsLong(RawContacts.VERSION); 2922644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 2932644d947574240b71c427d457f7a775dc160ec09Yorke Lee 2942644d947574240b71c427d457f7a775dc160ec09Yorke Lee /** 2952644d947574240b71c427d457f7a775dc160ec09Yorke Lee * Count number of {@link AggregationExceptions} updates contained in the 296f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang * given list of {@link CPOWrapper}. 2972644d947574240b71c427d457f7a775dc160ec09Yorke Lee */ 298f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang static int countExceptionUpdates(ArrayList<CPOWrapper> diff) { 2992644d947574240b71c427d457f7a775dc160ec09Yorke Lee int updateCount = 0; 300f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang for (CPOWrapper cpoWrapper : diff) { 301f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang final ContentProviderOperation oper = cpoWrapper.getOperation(); 3022644d947574240b71c427d457f7a775dc160ec09Yorke Lee if (AggregationExceptions.CONTENT_URI.equals(oper.getUri()) 303f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang && CompatUtils.isUpdateCompat(cpoWrapper)) { 3042644d947574240b71c427d457f7a775dc160ec09Yorke Lee updateCount++; 3052644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3062644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3072644d947574240b71c427d457f7a775dc160ec09Yorke Lee return updateCount; 3082644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3092644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3102644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testInsert() { 3112644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insert = getInsert(); 3122644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList set = buildSet(insert); 3132644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3142644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Inserting single shouldn't create rules 315f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang final ArrayList<CPOWrapper> diff = set.buildDiffWrapper(); 3162644d947574240b71c427d457f7a775dc160ec09Yorke Lee final int exceptionCount = countExceptionUpdates(diff); 3172644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected exception updates", 0, exceptionCount); 3182644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3192644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3202644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testUpdateUpdate() { 3212644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta updateFirst = getUpdate(mContext, CONTACT_FIRST); 3222644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta updateSecond = getUpdate(mContext, CONTACT_SECOND); 3232644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList set = buildSet(updateFirst, updateSecond); 3242644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3252644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Updating two existing shouldn't create rules 326f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang final ArrayList<CPOWrapper> diff = set.buildDiffWrapper(); 3272644d947574240b71c427d457f7a775dc160ec09Yorke Lee final int exceptionCount = countExceptionUpdates(diff); 3282644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected exception updates", 0, exceptionCount); 3292644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3302644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3312644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testUpdateInsert() { 3322644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta update = getUpdate(mContext, CONTACT_FIRST); 3332644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insert = getInsert(); 3342644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList set = buildSet(update, insert); 3352644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3362644d947574240b71c427d457f7a775dc160ec09Yorke Lee // New insert should only create one rule 337f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang final ArrayList<CPOWrapper> diff = set.buildDiffWrapper(); 3382644d947574240b71c427d457f7a775dc160ec09Yorke Lee final int exceptionCount = countExceptionUpdates(diff); 3392644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected exception updates", 1, exceptionCount); 3402644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3412644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3422644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testInsertUpdateInsert() { 3432644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insertFirst = getInsert(); 3442644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta update = getUpdate(mContext, CONTACT_FIRST); 3452644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insertSecond = getInsert(); 3462644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList set = buildSet(insertFirst, update, insertSecond); 3472644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3482644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Two inserts should create two rules to bind against single existing 349f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang final ArrayList<CPOWrapper> diff = set.buildDiffWrapper(); 3502644d947574240b71c427d457f7a775dc160ec09Yorke Lee final int exceptionCount = countExceptionUpdates(diff); 3512644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected exception updates", 2, exceptionCount); 3522644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3532644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3542644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testInsertInsertInsert() { 3552644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insertFirst = getInsert(); 3562644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insertSecond = getInsert(); 3572644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta insertThird = getInsert(); 3582644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList set = buildSet(insertFirst, insertSecond, insertThird); 3592644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3602644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Three new inserts should create only two binding rules 361f46a619e0126f3a2fd6048b5d6a07fcf26c3b38aWenyi Wang final ArrayList<CPOWrapper> diff = set.buildDiffWrapper(); 3622644d947574240b71c427d457f7a775dc160ec09Yorke Lee final int exceptionCount = countExceptionUpdates(diff); 3632644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected exception updates", 2, exceptionCount); 3642644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3652644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3662644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeDataRemoteInsert() { 3672644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 3682644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 3692644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 3702644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED), buildPhone(PHONE_GREEN))); 3712644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3722644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in second version, verify they match 3732644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 3742644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals("Unexpected change when merging", second, merged); 3752644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 3762644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3772644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeDataLocalUpdateRemoteInsert() { 3782644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 3792644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 3802644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 3812644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED), buildPhone(PHONE_GREEN))); 3822644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3832644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Change the local number to trigger update 3842644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta phone = getPhone(first, CONTACT_BOB, PHONE_RED); 3852644d947574240b71c427d457f7a775dc160ec09Yorke Lee phone.put(Phone.NUMBER, TEST_PHONE); 3862644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3872644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 3882644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 3892644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 390009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()), 3912644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 3922644d947574240b71c427d457f7a775dc160ec09Yorke Lee 3932644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in the second version, verify diff matches 3942644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 3952644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged, 3962644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 3972644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 398009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()), 3992644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4002644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 4012644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4022644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeDataLocalUpdateRemoteDelete() { 4032644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4042644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 4052644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4062644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_GREEN))); 4072644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4082644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Change the local number to trigger update 4092644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta phone = getPhone(first, CONTACT_BOB, PHONE_RED); 4102644d947574240b71c427d457f7a775dc160ec09Yorke Lee phone.put(Phone.NUMBER, TEST_PHONE); 4112644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4122644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 4132644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 4142644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 415009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()), 4162644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4172644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4182644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in the second version, verify that our update changed to 4192644d947574240b71c427d457f7a775dc160ec09Yorke Lee // insert, since RED was deleted on remote side 4202644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 4212644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged, 4222644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 4232644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 424009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(phone, CONTACT_BOB)), 4252644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4262644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 4272644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4282644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeDataLocalDeleteRemoteUpdate() { 4292644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4302644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 4312644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4322644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED, TEST_PHONE))); 4332644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4342644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Delete phone locally 4352644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta phone = getPhone(first, CONTACT_BOB, PHONE_RED); 4362644d947574240b71c427d457f7a775dc160ec09Yorke Lee phone.markDeleted(); 4372644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4382644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 4392644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 4402644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 4412644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildDelete(Data.CONTENT_URI), 4422644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4432644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4442644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in the second version, verify that our delete remains 4452644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 4462644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged, 4472644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 4482644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 4492644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildDelete(Data.CONTENT_URI), 4502644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4512644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 4522644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4532644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeDataLocalInsertRemoteInsert() { 4542644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4552644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 4562644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4572644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED), buildPhone(PHONE_GREEN))); 4582644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4592644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Insert new phone locally 4602644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta bluePhone = ValuesDelta.fromAfter(buildPhone(PHONE_BLUE)); 4612644d947574240b71c427d457f7a775dc160ec09Yorke Lee first.getByRawContactId(CONTACT_BOB).addEntry(bluePhone); 4622644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 4632644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 4642644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 465009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bluePhone, CONTACT_BOB)), 4662644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4672644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4682644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in the second version, verify that our insert remains 4692644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 4702644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged, 4712644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 4722644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 473009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bluePhone, CONTACT_BOB)), 4742644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 4752644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 4762644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4772644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeRawContactLocalInsertRemoteInsert() { 4782644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4792644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 4802644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 4812644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED)), buildBeforeEntity(mContext, CONTACT_MARY, 4822644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED))); 4832644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4842644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Add new contact locally, should remain insert 4852644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues joePhoneInsert = buildPhone(PHONE_BLUE); 4862644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta joeContact = buildAfterEntity(joePhoneInsert); 4872644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues joeContactInsert = joeContact.getValues().getCompleteValues(); 4882644d947574240b71c427d457f7a775dc160ec09Yorke Lee joeContactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED); 4892644d947574240b71c427d457f7a775dc160ec09Yorke Lee first.add(joeContact); 4902644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 4912644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 492009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(RawContacts.CONTENT_URI, TYPE_INSERT, joeContactInsert), 493009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, joePhoneInsert), 4942644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT), 4952644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationKeepTogether(CONTACT_BOB)); 4962644d947574240b71c427d457f7a775dc160ec09Yorke Lee 4972644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in the second version, verify that our insert remains 4982644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 4992644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged, 5002644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 5012644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 502009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(RawContacts.CONTENT_URI, TYPE_INSERT, joeContactInsert), 503009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, joePhoneInsert), 5042644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT), 5052644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationKeepTogether(CONTACT_BOB)); 5062644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 5072644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5082644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeRawContactLocalDeleteRemoteDelete() { 5092644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet( 5102644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildBeforeEntity(mContext, CONTACT_BOB, VER_FIRST, buildPhone(PHONE_RED)), 5112644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildBeforeEntity(mContext, CONTACT_MARY, VER_FIRST, buildPhone(PHONE_RED))); 5122644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet( 5132644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildBeforeEntity(mContext, CONTACT_BOB, VER_SECOND, buildPhone(PHONE_RED))); 5142644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5152644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Remove contact locally 5162644d947574240b71c427d457f7a775dc160ec09Yorke Lee first.getByRawContactId(CONTACT_MARY).markDeleted(); 5172644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 5182644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 5192644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 5202644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildDelete(RawContacts.CONTENT_URI)); 5212644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5222644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge in the second version, verify that our delete isn't needed 5232644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 5242644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged); 5252644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 5262644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5272644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeRawContactLocalUpdateRemoteDelete() { 5282644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet( 5292644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildBeforeEntity(mContext, CONTACT_BOB, VER_FIRST, buildPhone(PHONE_RED)), 5302644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildBeforeEntity(mContext, CONTACT_MARY, VER_FIRST, buildPhone(PHONE_RED))); 5312644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet( 5322644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildBeforeEntity(mContext, CONTACT_BOB, VER_SECOND, buildPhone(PHONE_RED))); 5332644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5342644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Perform local update 5352644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta phone = getPhone(first, CONTACT_MARY, PHONE_RED); 5362644d947574240b71c427d457f7a775dc160ec09Yorke Lee phone.put(Phone.NUMBER, TEST_PHONE); 5372644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 5382644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 5392644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 5402644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 541009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_UPDATE, phone.getAfter()), 5422644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 5432644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5442644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues phoneInsert = phone.getCompleteValues(); 5452644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ContentValues contactInsert = first.getByRawContactId(CONTACT_MARY).getValues() 5462644d947574240b71c427d457f7a775dc160ec09Yorke Lee .getCompleteValues(); 5472644d947574240b71c427d457f7a775dc160ec09Yorke Lee contactInsert.put(RawContacts.AGGREGATION_MODE, RawContacts.AGGREGATION_MODE_SUSPENDED); 5482644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5492644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Merge and verify that update turned into insert 5502644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 5512644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged, 5522644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_SECOND), 553009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(RawContacts.CONTENT_URI, TYPE_INSERT, contactInsert), 554009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, phoneInsert), 5552644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAggregationModeUpdate(RawContacts.AGGREGATION_MODE_DEFAULT), 5562644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationKeepTogether(CONTACT_BOB)); 5572644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 5582644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5592644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeUsesNewVersion() { 5602644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 5612644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildPhone(PHONE_RED))); 5622644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 5632644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildPhone(PHONE_RED))); 5642644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5652644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals((Long)VER_FIRST, getVersion(first, CONTACT_BOB)); 5662644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals((Long)VER_SECOND, getVersion(second, CONTACT_BOB)); 5672644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5682644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 5692644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertEquals((Long)VER_SECOND, getVersion(merged, CONTACT_BOB)); 5702644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 5712644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5722644d947574240b71c427d457f7a775dc160ec09Yorke Lee public void testMergeAfterEnsureAndTrim() { 5732644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList first = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 5742644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_FIRST, buildEmail(EMAIL_YELLOW))); 5752644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList second = buildSet(buildBeforeEntity(mContext, CONTACT_BOB, 5762644d947574240b71c427d457f7a775dc160ec09Yorke Lee VER_SECOND, buildEmail(EMAIL_YELLOW))); 5772644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5782644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Ensure we have at least one phone 5792644d947574240b71c427d457f7a775dc160ec09Yorke Lee final AccountType source = getAccountType(); 5802644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDelta bobContact = first.getByRawContactId(CONTACT_BOB); 5812644d947574240b71c427d457f7a775dc160ec09Yorke Lee RawContactModifier.ensureKindExists(bobContact, source, Phone.CONTENT_ITEM_TYPE); 5822644d947574240b71c427d457f7a775dc160ec09Yorke Lee final ValuesDelta bobPhone = bobContact.getSuperPrimaryEntry(Phone.CONTENT_ITEM_TYPE, true); 5832644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5842644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Make sure the update would insert a row 5852644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first, 5862644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildAssertVersion(VER_FIRST), 5872644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationSuspended(), 588009d63c3d9c9dd372137c4954fb8562f5b132d60Wenyi Wang buildCPOWrapper(Data.CONTENT_URI, TYPE_INSERT, buildDataInsert(bobPhone, CONTACT_BOB)), 5892644d947574240b71c427d457f7a775dc160ec09Yorke Lee buildUpdateAggregationDefault()); 5902644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5912644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Trim values and ensure that we don't insert things 5922644d947574240b71c427d457f7a775dc160ec09Yorke Lee RawContactModifier.trimEmpty(bobContact, source); 5932644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(first); 5942644d947574240b71c427d457f7a775dc160ec09Yorke Lee 5952644d947574240b71c427d457f7a775dc160ec09Yorke Lee // Now re-parent the change, which should remain no-op 5962644d947574240b71c427d457f7a775dc160ec09Yorke Lee final RawContactDeltaList merged = RawContactDeltaList.mergeAfter(second, first); 5972644d947574240b71c427d457f7a775dc160ec09Yorke Lee assertDiffPattern(merged); 5982644d947574240b71c427d457f7a775dc160ec09Yorke Lee } 5992644d947574240b71c427d457f7a775dc160ec09Yorke Lee} 600