EntityModifierTests.java revision 405671a7b42d97ebf7ae7c0eeb4721f881139673
107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey/*
207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * Copyright (C) 2009 The Android Open Source Project
307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey *
407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * you may not use this file except in compliance with the License.
607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * You may obtain a copy of the License at
707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey *
807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey *
1007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
1107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
1207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * See the License for the specific language governing permissions and
1407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * limitations under the License.
1507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey */
1607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
1707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeypackage com.android.contacts;
1807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
196f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkeyimport static android.content.ContentProviderOperation.TYPE_DELETE;
206f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkeyimport static android.content.ContentProviderOperation.TYPE_INSERT;
216f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkeyimport static android.content.ContentProviderOperation.TYPE_UPDATE;
226f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
234597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType;
244597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikovimport com.android.contacts.model.AccountType.EditType;
251173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport com.android.contacts.model.AccountTypeManager;
26405671a7b42d97ebf7ae7c0eeb4721f881139673Daisuke Miyakawaimport com.android.contacts.model.DataKind;
271173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport com.android.contacts.model.EntityDelta;
286f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkeyimport com.android.contacts.model.EntityDelta.ValuesDelta;
291173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport com.android.contacts.model.EntityDeltaList;
301173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport com.android.contacts.model.EntityModifier;
311173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport com.android.contacts.tests.mocks.MockAccountTypeManager;
32aad8848282f51d73ad308e9ad3ebcef592fa153fJeff Sharkeyimport com.google.android.collect.Lists;
3307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
346f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkeyimport android.content.ContentProviderOperation;
3507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.content.ContentValues;
36ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkeyimport android.content.Context;
3707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.content.Entity;
3816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.os.Bundle;
397173705177c421e0b2a3bc4579b2f8910a38a668Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email;
4016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Im;
4116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Organization;
4207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Phone;
4316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
4416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
451173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport android.provider.ContactsContract.Data;
461173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport android.provider.ContactsContract.Intents.Insert;
471173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
4807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.test.AndroidTestCase;
4907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.test.suitebuilder.annotation.LargeTest;
5007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
5107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport java.util.ArrayList;
5207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport java.util.List;
5307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
5407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey/**
554597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikov * Tests for {@link EntityModifier} to verify that {@link AccountType}
5607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * constraints are being enforced correctly.
5707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey */
5807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey@LargeTest
5907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeypublic class EntityModifierTests extends AndroidTestCase {
6007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public static final String TAG = "EntityModifierTests";
6107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
62e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    public static final long VER_FIRST = 100;
63e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
646f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    private static final long TEST_ID = 4;
656f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    private static final String TEST_PHONE = "218-555-1212";
6616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_NAME = "Adam Young";
6716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_NAME2 = "Breanne Duren";
6816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_IM = "example@example.com";
6916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_POSTAL = "1600 Amphitheatre Parkway";
706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
717f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    private static final String TEST_ACCOUNT_NAME = "unittest@example.com";
727f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    private static final String TEST_ACCOUNT_TYPE = "com.example.unittest";
737f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
7407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    @Override
7507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void setUp() {
7607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        mContext = getContext();
7707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
7807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
794597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikov    public static class MockContactsSource extends AccountType {
80b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov
81b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        MockContactsSource() {
82ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey            this.accountType = TEST_ACCOUNT_TYPE;
8307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
846c9b4b97752e415528279464b28560d389256783Daniel Lehmann            final DataKind nameKind = new DataKind(StructuredName.CONTENT_ITEM_TYPE,
856c9b4b97752e415528279464b28560d389256783Daniel Lehmann                    R.string.nameLabelsGroup, -1, -1, true);
866c9b4b97752e415528279464b28560d389256783Daniel Lehmann            nameKind.typeOverallMax = 1;
876c9b4b97752e415528279464b28560d389256783Daniel Lehmann            addKind(nameKind);
886c9b4b97752e415528279464b28560d389256783Daniel Lehmann
8907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey            // Phone allows maximum 2 home, 1 work, and unlimited other, with
9007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey            // constraint of 5 numbers maximum.
916c9b4b97752e415528279464b28560d389256783Daniel Lehmann            final DataKind phoneKind = new DataKind(Phone.CONTENT_ITEM_TYPE, -1, -1, 10, true);
9207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
936c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeOverallMax = 5;
946c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeColumn = Phone.TYPE;
956c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeList = Lists.newArrayList();
966c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeList.add(new EditType(Phone.TYPE_HOME, -1).setSpecificMax(2));
976c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeList.add(new EditType(Phone.TYPE_WORK, -1).setSpecificMax(1));
986c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeList.add(new EditType(Phone.TYPE_FAX_WORK, -1).setSecondary(true));
996c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.typeList.add(new EditType(Phone.TYPE_OTHER, -1));
10007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
1016c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.fieldList = Lists.newArrayList();
1026c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.fieldList.add(new EditField(Phone.NUMBER, -1, -1));
1036c9b4b97752e415528279464b28560d389256783Daniel Lehmann            phoneKind.fieldList.add(new EditField(Phone.LABEL, -1, -1));
1046f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
1056c9b4b97752e415528279464b28560d389256783Daniel Lehmann            addKind(phoneKind);
1067173705177c421e0b2a3bc4579b2f8910a38a668Jeff Sharkey
1077173705177c421e0b2a3bc4579b2f8910a38a668Jeff Sharkey            // Email is unlimited
1086c9b4b97752e415528279464b28560d389256783Daniel Lehmann            final DataKind emailKind = new DataKind(Email.CONTENT_ITEM_TYPE, -1, -1, 10, true);
1096c9b4b97752e415528279464b28560d389256783Daniel Lehmann            emailKind.typeOverallMax = -1;
1106c9b4b97752e415528279464b28560d389256783Daniel Lehmann            emailKind.fieldList = Lists.newArrayList();
1116c9b4b97752e415528279464b28560d389256783Daniel Lehmann            emailKind.fieldList.add(new EditField(Email.DATA, -1, -1));
1126c9b4b97752e415528279464b28560d389256783Daniel Lehmann            addKind(emailKind);
11316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
11416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey            // IM is only one
1156c9b4b97752e415528279464b28560d389256783Daniel Lehmann            final DataKind imKind = new DataKind(Im.CONTENT_ITEM_TYPE, -1, -1, 10, true);
1166c9b4b97752e415528279464b28560d389256783Daniel Lehmann            imKind.typeOverallMax = 1;
1176c9b4b97752e415528279464b28560d389256783Daniel Lehmann            imKind.fieldList = Lists.newArrayList();
1186c9b4b97752e415528279464b28560d389256783Daniel Lehmann            imKind.fieldList.add(new EditField(Im.DATA, -1, -1));
1196c9b4b97752e415528279464b28560d389256783Daniel Lehmann            addKind(imKind);
1207173705177c421e0b2a3bc4579b2f8910a38a668Jeff Sharkey
12116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey            // Organization is only one
1226c9b4b97752e415528279464b28560d389256783Daniel Lehmann            final DataKind orgKind = new DataKind(Organization.CONTENT_ITEM_TYPE, -1, -1, 10, true);
1236c9b4b97752e415528279464b28560d389256783Daniel Lehmann            orgKind.typeOverallMax = 1;
1246c9b4b97752e415528279464b28560d389256783Daniel Lehmann            orgKind.fieldList = Lists.newArrayList();
1256c9b4b97752e415528279464b28560d389256783Daniel Lehmann            orgKind.fieldList.add(new EditField(Organization.COMPANY, -1, -1));
1266c9b4b97752e415528279464b28560d389256783Daniel Lehmann            orgKind.fieldList.add(new EditField(Organization.TITLE, -1, -1));
1276c9b4b97752e415528279464b28560d389256783Daniel Lehmann            addKind(orgKind);
12807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        }
1295297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton
1305297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        @Override
1315297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        public int getHeaderColor(Context context) {
1325297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton            return 0;
1335297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        }
1345297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton
1355297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        @Override
1365297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        public int getSideBarColor(Context context) {
1375297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton            return 0xffffff;
1385297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        }
139ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey    }
14007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
141ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey    /**
1424597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikov     * Build a {@link AccountType} that has various odd constraints for
143ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey     * testing purposes.
144ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey     */
145b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov    protected AccountType getAccountType() {
146b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        return new MockContactsSource();
14707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
14807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
14907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
150a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov     * Build {@link AccountTypeManager} instance.
1517f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey     */
152a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov    protected AccountTypeManager getAccountTypes(AccountType... types) {
1531173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov        return new MockAccountTypeManager(types, null);
1547f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
1557f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
1567f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    /**
15707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Build an {@link Entity} with the requested set of phone numbers.
15807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
1597f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    protected EntityDelta getEntity(Long existingId, ContentValues... entries) {
16007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final ContentValues contact = new ContentValues();
1617f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        if (existingId != null) {
1627f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            contact.put(RawContacts._ID, existingId);
1637f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
1647f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        contact.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
1657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT_TYPE);
1667f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
16707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final Entity before = new Entity(contact);
1686f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        for (ContentValues values : entries) {
1696f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            before.addSubValue(Data.CONTENT_URI, values);
1706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
1718d9767d79f9fe2a09ee6e981b1fede7e9863d62aJeff Sharkey        return EntityDelta.fromBefore(before);
17207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
17307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
17407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
17507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Assert this {@link List} contains the given {@link Object}.
17607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
17707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    protected void assertContains(List<?> list, Object object) {
17807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertTrue("Missing expected value", list.contains(object));
17907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
18007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
18107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
18207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Assert this {@link List} does not contain the given {@link Object}.
18307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
18407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    protected void assertNotContains(List<?> list, Object object) {
18507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertFalse("Contained unexpected value", list.contains(object));
18607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
18707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
18807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
18907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Insert various rows to test
1908d9767d79f9fe2a09ee6e981b1fede7e9863d62aJeff Sharkey     * {@link EntityModifier#getValidTypes(EntityDelta, DataKind, EditType)}
19107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
19207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void testValidTypes() {
19307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Build a source and pull specific types
194b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
19507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
19607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
19707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
19807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
19907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
20007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        List<EditType> validTypes;
20107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
20207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add first home, first work
2037f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
20407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
20507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeWork);
20607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
20707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Expecting home, other
20807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
20907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertContains(validTypes, typeHome);
21007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeWork);
21107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertContains(validTypes, typeOther);
21207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
21307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add second home
21407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
21507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
21607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Expecting other
21707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
21807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeHome);
21907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeWork);
22007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertContains(validTypes, typeOther);
22107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
22207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add third and fourth home (invalid, but possible)
22307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
22407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
22507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
22607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Expecting none
22707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
22807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeHome);
22907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeWork);
23007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeOther);
23107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
23207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
23307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
2348d9767d79f9fe2a09ee6e981b1fede7e9863d62aJeff Sharkey     * Test {@link EntityModifier#canInsert(EntityDelta, DataKind)} by
23507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * inserting various rows.
23607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
23707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void testCanInsert() {
23807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Build a source and pull specific types
239b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
24007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
24107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
24207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
24307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
24407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
24507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add first home, first work
2467f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
24707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
24807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeWork);
24907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertTrue("Unable to insert", EntityModifier.canInsert(state, kindPhone));
25007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
25107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add two other, which puts us just under "5" overall limit
25207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeOther);
25307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeOther);
25407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertTrue("Unable to insert", EntityModifier.canInsert(state, kindPhone));
25507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
25607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add second home, which should push to snug limit
25707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
25807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertFalse("Able to insert", EntityModifier.canInsert(state, kindPhone));
25907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
26007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
26107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
262d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey     * Test
263d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey     * {@link EntityModifier#getBestValidType(EntityDelta, DataKind, boolean, int)}
26407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * by asserting expected best options in various states.
26507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
26607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void testBestValidType() {
26707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Build a source and pull specific types
268b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
26907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
27007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
27107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
27207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeFaxWork = EntityModifier.getType(kindPhone, Phone.TYPE_FAX_WORK);
27307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
27407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
27507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EditType suggested;
27607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
27707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Default suggestion should be home
2787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
279d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
28007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeHome, suggested);
28107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
28207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add first home, should now suggest work
28307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
284d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
28507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeWork, suggested);
28607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
28707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add work fax, should still suggest work
28807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeFaxWork);
289d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
29007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeWork, suggested);
29107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
29207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add other, should still suggest work
29307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeOther);
294d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
29507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeWork, suggested);
29607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
29707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add work, now should suggest other
29807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeWork);
299d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
30007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeOther, suggested);
30107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
3026f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3036f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testIsEmptyEmpty() {
304b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
3056f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
3066f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3076f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Test entirely empty row
3086f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ContentValues after = new ContentValues();
3096f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ValuesDelta values = ValuesDelta.fromAfter(after);
3106f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3116f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertTrue("Expected empty", EntityModifier.isEmpty(values, kindPhone));
3126f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
3136f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3146f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testIsEmptyDirectFields() {
315b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
3166f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
3176f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
3186f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3196f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Test row that has type values, but core fields are empty
3207f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
3216f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
3226f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3236f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertTrue("Expected empty", EntityModifier.isEmpty(values, kindPhone));
3246f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3256f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Insert some data to trigger non-empty state
3266f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        values.put(Phone.NUMBER, TEST_PHONE);
3276f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3286f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertFalse("Expected non-empty", EntityModifier.isEmpty(values, kindPhone));
3296f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
3306f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3316f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testTrimEmptySingle() {
332b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
3336f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
3346f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
3356f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3366f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Test row that has type values, but core fields are empty
3377f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
3386c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.insertChild(state, kindPhone, typeHome);
3396f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3406f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build diff, expecting insert for data row and update enforcement
3416f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
3426f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
3436f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
3446f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
3456f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(0);
3466f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
3476f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3486f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
3496f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
3506f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(1);
3516f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
3526f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
3536f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
3546f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
3556f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(2);
3566f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
3576f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3586f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
3596f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3607f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Trim empty rows and try again, expecting delete of overall contact
3617f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        EntityModifier.trimEmpty(state, source);
3626f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
3636f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
3647f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 1, diff.size());
3657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
3667f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
3677f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
3687f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3697f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
3706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
3716f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
372e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    public void testTrimEmptySpaces() {
373b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
374e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
375e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
376e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
377e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Test row that has type values, but values are spaces
378ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDelta state = EntityDeltaListTests.buildBeforeEntity(TEST_ID, VER_FIRST);
379e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
380e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        values.put(Phone.NUMBER, "   ");
381e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
382e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Build diff, expecting insert for data row and update enforcement
383ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
384ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
385ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationSuspended(),
386ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
387ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
388ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationDefault());
389e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
390e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Trim empty rows and try again, expecting delete of overall contact
391e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        EntityModifier.trimEmpty(state, source);
392ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
393ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
394ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildDelete(RawContacts.CONTENT_URI));
395e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    }
396e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
397e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    public void testTrimLeaveValid() {
398b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
399e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
400e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
401e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
402e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Test row that has type values with valid number
403ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDelta state = EntityDeltaListTests.buildBeforeEntity(TEST_ID, VER_FIRST);
404e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
405e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        values.put(Phone.NUMBER, TEST_PHONE);
406e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
407e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Build diff, expecting insert for data row and update enforcement
408ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
409ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
410ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationSuspended(),
411ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
412ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
413ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationDefault());
414e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
415e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Trim empty rows and try again, expecting no differences
416e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        EntityModifier.trimEmpty(state, source);
417ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
418ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
419ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationSuspended(),
420ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
421ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
422ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationDefault());
423e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    }
424e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
4256f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testTrimEmptyUntouched() {
426b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
4276f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
4286c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
4296f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4306f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build "before" that has empty row
4317f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
4326f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ContentValues before = new ContentValues();
4336f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data._ID, TEST_ID);
4346f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
4356f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.addEntry(ValuesDelta.fromBefore(before));
4366f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4376f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build diff, expecting no changes
4386f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
4396f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4406f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
4416f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4426f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Try trimming existing empty, which we shouldn't touch
4437f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        EntityModifier.trimEmpty(state, source);
4446f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
4456f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4466f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
4476f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
4486f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4496f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testTrimEmptyAfterUpdate() {
450b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
4516f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
4526f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
4536f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4546f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build "before" that has row with some phone number
4556f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ContentValues before = new ContentValues();
4566f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data._ID, TEST_ID);
4576f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
4586f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(kindPhone.typeColumn, typeHome.rawValue);
4596f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Phone.NUMBER, TEST_PHONE);
4607f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, before);
4616f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4626f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build diff, expecting no changes
4636f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
4646f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4656f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
4666f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4676f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Now update row by changing number to empty string, expecting single update
4686f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ValuesDelta child = state.getEntry(TEST_ID);
4696f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        child.put(Phone.NUMBER, "");
4706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
4716f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4726f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
4736f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
4746f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(0);
4756f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
4766f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
4776f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
4786f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
4796f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(1);
4806f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
4816f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
4826f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
4836f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
4846f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(2);
4856f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
4866f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
4876f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
4886f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4896f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Now run trim, which should turn that update into delete
4907f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        EntityModifier.trimEmpty(state, source);
4917f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
4927f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
4937f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 1, diff.size());
4947f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
4957f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
4967f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
4977f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
4987f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
4997f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
5007f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5017f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimInsertEmpty() {
502a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
503a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
504a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
5056c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
5067f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5077f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Try creating a contact without any child entries
5087f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(null);
509ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
5107f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5117f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting single insert
5127f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
5137f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5143aba36cc373e82ca3a3331bb77bd1278d0afde06Dmitri Plotnikov        assertEquals("Unexpected operations", 2, diff.size());
5157f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5167f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
5177f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
5187f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5197f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5207f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5217f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Trim empty rows and try again, expecting no insert
522a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
5237f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
5247f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5257f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
5267f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
5277f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5287f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimInsertInsert() {
529a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
530a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
531a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
5327f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
5337f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5347f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Try creating a contact with single empty entry
5357f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(null);
5366c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.insertChild(state, kindPhone, typeHome);
537ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
5387f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5397f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting two insert operations
5407f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
5417f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5423aba36cc373e82ca3a3331bb77bd1278d0afde06Dmitri Plotnikov        assertEquals("Unexpected operations", 3, diff.size());
5437f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5447f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
5457f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
5467f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5477f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5487f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5497f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(1);
5507f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
5517f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
5527f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5537f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5547f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Trim empty rows and try again, expecting silence
555a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
5567f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
5577f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5587f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
5597f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
5607f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5617f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimUpdateRemain() {
562a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
563a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
564a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
5657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
5667f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5677f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build "before" with two phone numbers
5687f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ContentValues first = new ContentValues();
5697f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data._ID, TEST_ID);
5707f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
5717f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(kindPhone.typeColumn, typeHome.rawValue);
5727f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Phone.NUMBER, TEST_PHONE);
5737f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5747f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ContentValues second = new ContentValues();
5757f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(Data._ID, TEST_ID);
5767f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
5777f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(kindPhone.typeColumn, typeHome.rawValue);
5787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(Phone.NUMBER, TEST_PHONE);
5797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5807f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first, second);
581ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
5827f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5837f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting no changes
5847f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
5857f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5867f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
5877f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5887f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now update row by changing number to empty string, expecting single update
5897f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ValuesDelta child = state.getEntry(TEST_ID);
5907f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        child.put(Phone.NUMBER, "");
5917f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
5927f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5937f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
5947f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5957f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
5967f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
5977f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5987f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5997f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6007f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(1);
6017f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
6027f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
6037f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6047f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6057f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(2);
6067f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6077f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6087f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6097f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6107f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now run trim, which should turn that update into delete
611a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
6126f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
6136f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
6146f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
6156f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
6166f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6176f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6186f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6196f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
6206f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
6216f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(1);
6226f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
6236f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
6246f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
6256f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
6266f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(2);
6276f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6286f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6296f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
6306f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
6317f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6327f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimUpdateUpdate() {
633a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
634a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
635a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
6367f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
6377f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6387f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build "before" with two phone numbers
6397f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ContentValues first = new ContentValues();
6407f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data._ID, TEST_ID);
6417f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
6427f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(kindPhone.typeColumn, typeHome.rawValue);
6437f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Phone.NUMBER, TEST_PHONE);
6447f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6457f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first);
646ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
6477f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6487f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting no changes
6497f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
6507f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6517f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
6527f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6537f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now update row by changing number to empty string, expecting single update
6547f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ValuesDelta child = state.getEntry(TEST_ID);
6557f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        child.put(Phone.NUMBER, "");
6567f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
6577f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6587f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
6597f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6607f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6617f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6627f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6637f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6647f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(1);
6667f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
6677f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
6687f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6697f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6707f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(2);
6717f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6727f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6737f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6747f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6757f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now run trim, which should turn into deleting the whole contact
676a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
6777f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
6787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 1, diff.size());
6807f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6817f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6827f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
6837f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6847f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6857f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
68616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
68716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasExistingName() {
688a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
68916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
69016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Build "before" name
69116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final ContentValues first = new ContentValues();
69216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data._ID, TEST_ID);
69316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
69416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(StructuredName.GIVEN_NAME, TEST_NAME);
69516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
69616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Parse extras, making sure we keep single name
69716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first);
69816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
69916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.NAME, TEST_NAME2);
700a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
70116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
70216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int nameCount = state.getMimeEntriesCount(StructuredName.CONTENT_ITEM_TYPE, true);
70316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        assertEquals("Unexpected names", 1, nameCount);
70416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
70516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
70616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasIgnoreLimit() {
707a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
70816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
70916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Build "before" IM
71016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final ContentValues first = new ContentValues();
71116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data._ID, TEST_ID);
71216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
71316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Im.DATA, TEST_IM);
71416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
71516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first);
71616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int beforeCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
71716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
718a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        // We should ignore data that doesn't fit account type rules, since account type
71916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // only allows single Im
72016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
72116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putInt(Insert.IM_PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
72216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.IM_HANDLE, TEST_IM);
723a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
72416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
72516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int afterCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
726a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        assertEquals("Broke account type rules", beforeCount, afterCount);
72716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
72816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
72916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasIgnoreUnhandled() {
730a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
73116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
73216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
733a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        // We should silently ignore types unsupported by account type
73416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
73516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.POSTAL, TEST_POSTAL);
736a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
73716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
738a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        assertNull("Broke accoun type rules",
739a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov                state.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
74016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
74116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
74216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasJobTitle() {
743a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
74416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
74516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
74616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Make sure that we create partial Organizations
74716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
74816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.JOB_TITLE, TEST_NAME);
749a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
75016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
75116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int count = state.getMimeEntries(Organization.CONTENT_ITEM_TYPE).size();
75216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        assertEquals("Expected to create organization", 1, count);
75316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
75407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey}
755