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;
31d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.model.ExchangeAccountType;
32d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.model.GoogleAccountType;
33d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.tests.mocks.ContactsMockContext;
341173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport com.android.contacts.tests.mocks.MockAccountTypeManager;
35d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport com.android.contacts.tests.mocks.MockContentProvider;
3686ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onukiimport com.google.android.collect.Lists;
3707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
386f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkeyimport android.content.ContentProviderOperation;
3907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.content.ContentValues;
4007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.content.Entity;
41d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.net.Uri;
4216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.os.Bundle;
43d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.provider.ContactsContract;
447173705177c421e0b2a3bc4579b2f8910a38a668Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Email;
45d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawaimport android.provider.ContactsContract.CommonDataKinds.Event;
4616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Im;
4716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Organization;
4807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.Phone;
4916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredName;
5016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkeyimport android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
511173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport android.provider.ContactsContract.Data;
521173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport android.provider.ContactsContract.Intents.Insert;
531173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikovimport android.provider.ContactsContract.RawContacts;
5407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.test.AndroidTestCase;
5507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport android.test.suitebuilder.annotation.LargeTest;
5607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
5707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport java.util.ArrayList;
5807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeyimport java.util.List;
5907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
6007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey/**
614597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikov * Tests for {@link EntityModifier} to verify that {@link AccountType}
6207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey * constraints are being enforced correctly.
6307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey */
6407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey@LargeTest
6507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkeypublic class EntityModifierTests extends AndroidTestCase {
6607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public static final String TAG = "EntityModifierTests";
6707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
68e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    public static final long VER_FIRST = 100;
69e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    private static final long TEST_ID = 4;
716f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    private static final String TEST_PHONE = "218-555-1212";
7216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_NAME = "Adam Young";
7316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_NAME2 = "Breanne Duren";
7416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_IM = "example@example.com";
7516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    private static final String TEST_POSTAL = "1600 Amphitheatre Parkway";
766f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
777f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    private static final String TEST_ACCOUNT_NAME = "unittest@example.com";
787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    private static final String TEST_ACCOUNT_TYPE = "com.example.unittest";
797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
8007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    @Override
8107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void setUp() {
8207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        mContext = getContext();
8307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
8407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
854597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikov    public static class MockContactsSource extends AccountType {
86b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov
87b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        MockContactsSource() {
8886ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki            try {
8986ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                this.accountType = TEST_ACCOUNT_TYPE;
9086ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
9186ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                final DataKind nameKind = new DataKind(StructuredName.CONTENT_ITEM_TYPE,
9286ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                        R.string.nameLabelsGroup, -1, true, -1);
9386ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                nameKind.typeOverallMax = 1;
9486ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                addKind(nameKind);
9586ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
9686ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                // Phone allows maximum 2 home, 1 work, and unlimited other, with
9786ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                // constraint of 5 numbers maximum.
9886ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                final DataKind phoneKind = new DataKind(
9986ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                        Phone.CONTENT_ITEM_TYPE, -1, 10, true, -1);
10086ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
10186ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeOverallMax = 5;
10286ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeColumn = Phone.TYPE;
10386ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeList = Lists.newArrayList();
10486ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeList.add(new EditType(Phone.TYPE_HOME, -1).setSpecificMax(2));
10586ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeList.add(new EditType(Phone.TYPE_WORK, -1).setSpecificMax(1));
10686ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeList.add(new EditType(Phone.TYPE_FAX_WORK, -1).setSecondary(true));
10786ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.typeList.add(new EditType(Phone.TYPE_OTHER, -1));
10886ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
10986ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.fieldList = Lists.newArrayList();
11086ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.fieldList.add(new EditField(Phone.NUMBER, -1, -1));
11186ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                phoneKind.fieldList.add(new EditField(Phone.LABEL, -1, -1));
11286ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
11386ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                addKind(phoneKind);
11486ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
11586ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                // Email is unlimited
11686ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                final DataKind emailKind = new DataKind(
11786ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                        Email.CONTENT_ITEM_TYPE, -1, 10, true, -1);
11886ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                emailKind.typeOverallMax = -1;
11986ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                emailKind.fieldList = Lists.newArrayList();
12086ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                emailKind.fieldList.add(new EditField(Email.DATA, -1, -1));
12186ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                addKind(emailKind);
12286ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
12386ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                // IM is only one
12486ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                final DataKind imKind = new DataKind(Im.CONTENT_ITEM_TYPE, -1, 10,
12586ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                        true, -1);
12686ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                imKind.typeOverallMax = 1;
12786ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                imKind.fieldList = Lists.newArrayList();
12886ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                imKind.fieldList.add(new EditField(Im.DATA, -1, -1));
12986ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                addKind(imKind);
13086ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki
13186ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                // Organization is only one
13286ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                final DataKind orgKind = new DataKind(
13386ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                        Organization.CONTENT_ITEM_TYPE, -1, 10, true, -1);
13486ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                orgKind.typeOverallMax = 1;
13586ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                orgKind.fieldList = Lists.newArrayList();
13686ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                orgKind.fieldList.add(new EditField(Organization.COMPANY, -1, -1));
13786ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                orgKind.fieldList.add(new EditField(Organization.TITLE, -1, -1));
13886ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                addKind(orgKind);
13986ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki            } catch (DefinitionException e) {
14086ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki                throw new RuntimeException(e);
14186ccb6ce2ff6078b06add93aab489951ef83bc72Makoto Onuki            }
14207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        }
1435297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton
1445297c6af41f3fd2f08cff5b84105af4efd1ab79fJeff Hamilton        @Override
145fd33cc3ab956222dffa6b669a13a614747a5cdffKatherine Kuan        public boolean isGroupMembershipEditable() {
146fd33cc3ab956222dffa6b669a13a614747a5cdffKatherine Kuan            return false;
147fd33cc3ab956222dffa6b669a13a614747a5cdffKatherine Kuan        }
14896e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann
14996e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann        @Override
15096e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann        public boolean areContactsWritable() {
15196e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann            return true;
15296e87fd6e808e9d853263ffeb5104f3253a18639Daniel Lehmann        }
153ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey    }
15407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
155ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey    /**
1564597c92d655d45447780b32c7572acef110b6ed1Dmitri Plotnikov     * Build a {@link AccountType} that has various odd constraints for
157ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey     * testing purposes.
158ab066931efd4b6408b5f57026b421eb4a7934a39Jeff Sharkey     */
159b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov    protected AccountType getAccountType() {
160b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        return new MockContactsSource();
16107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
16207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
16307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
164a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov     * Build {@link AccountTypeManager} instance.
1657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey     */
166a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov    protected AccountTypeManager getAccountTypes(AccountType... types) {
1671173ae29217fc83f254404f8a5fa10419ee83c93Dmitri Plotnikov        return new MockAccountTypeManager(types, null);
1687f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
1697f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
1707f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    /**
17107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Build an {@link Entity} with the requested set of phone numbers.
17207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
1737f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    protected EntityDelta getEntity(Long existingId, ContentValues... entries) {
17407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final ContentValues contact = new ContentValues();
1757f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        if (existingId != null) {
1767f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            contact.put(RawContacts._ID, existingId);
1777f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
1787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        contact.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME);
1797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT_TYPE);
1807f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
18107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final Entity before = new Entity(contact);
1826f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        for (ContentValues values : entries) {
1836f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            before.addSubValue(Data.CONTENT_URI, values);
1846f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
1858d9767d79f9fe2a09ee6e981b1fede7e9863d62aJeff Sharkey        return EntityDelta.fromBefore(before);
18607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
18707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
18807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
18907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Assert this {@link List} contains the given {@link Object}.
19007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
19107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    protected void assertContains(List<?> list, Object object) {
19207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertTrue("Missing expected value", list.contains(object));
19307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
19407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
19507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
19607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Assert this {@link List} does not contain the given {@link Object}.
19707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
19807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    protected void assertNotContains(List<?> list, Object object) {
19907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertFalse("Contained unexpected value", list.contains(object));
20007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
20107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
20207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
20307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * Insert various rows to test
2048d9767d79f9fe2a09ee6e981b1fede7e9863d62aJeff Sharkey     * {@link EntityModifier#getValidTypes(EntityDelta, DataKind, EditType)}
20507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
20607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void testValidTypes() {
20707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Build a source and pull specific types
208b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
20907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
21007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
21107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
21207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
21307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
21407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        List<EditType> validTypes;
21507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
21607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add first home, first work
2177f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
21807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
21907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeWork);
22007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
22107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Expecting home, other
22207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
22307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertContains(validTypes, typeHome);
22407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeWork);
22507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertContains(validTypes, typeOther);
22607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
22707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add second home
22807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
22907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
23007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Expecting other
23107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
23207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeHome);
23307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeWork);
23407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertContains(validTypes, typeOther);
23507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
23607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add third and fourth home (invalid, but possible)
23707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
23807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
23907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
24007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Expecting none
24107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        validTypes = EntityModifier.getValidTypes(state, kindPhone, null);
24207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeHome);
24307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeWork);
24407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertNotContains(validTypes, typeOther);
24507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
24607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
24707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
2488d9767d79f9fe2a09ee6e981b1fede7e9863d62aJeff Sharkey     * Test {@link EntityModifier#canInsert(EntityDelta, DataKind)} by
24907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * inserting various rows.
25007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
25107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void testCanInsert() {
25207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Build a source and pull specific types
253b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
25407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
25507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
25607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
25707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
25807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
25907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add first home, first work
2607f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
26107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
26207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeWork);
26307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertTrue("Unable to insert", EntityModifier.canInsert(state, kindPhone));
26407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
26507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add two other, which puts us just under "5" overall limit
26607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeOther);
26707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeOther);
26807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertTrue("Unable to insert", EntityModifier.canInsert(state, kindPhone));
26907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
27007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add second home, which should push to snug limit
27107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
27207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertFalse("Able to insert", EntityModifier.canInsert(state, kindPhone));
27307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
27407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
27507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    /**
276d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey     * Test
277d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey     * {@link EntityModifier#getBestValidType(EntityDelta, DataKind, boolean, int)}
27807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     * by asserting expected best options in various states.
27907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey     */
28007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    public void testBestValidType() {
28107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Build a source and pull specific types
282b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
28307c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
28407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
28507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeWork = EntityModifier.getType(kindPhone, Phone.TYPE_WORK);
28607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeFaxWork = EntityModifier.getType(kindPhone, Phone.TYPE_FAX_WORK);
28707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        final EditType typeOther = EntityModifier.getType(kindPhone, Phone.TYPE_OTHER);
28807c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
28907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EditType suggested;
29007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
29107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Default suggestion should be home
2927f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
293d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
29407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeHome, suggested);
29507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
29607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add first home, should now suggest work
29707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeHome);
298d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
29907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeWork, suggested);
30007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
30107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add work fax, should still suggest work
30207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeFaxWork);
303d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
30407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeWork, suggested);
30507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
30607c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add other, should still suggest work
30707c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeOther);
308d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
30907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeWork, suggested);
31007c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey
31107c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        // Add work, now should suggest other
31207c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        EntityModifier.insertChild(state, kindPhone, typeWork);
313d046a039e41deab0635c3327cd40c3896e39acadJeff Sharkey        suggested = EntityModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE);
31407c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey        assertEquals("Unexpected suggestion", typeOther, suggested);
31507c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey    }
3166f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3176f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testIsEmptyEmpty() {
318b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
3196f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
3206f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3216f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Test entirely empty row
3226f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ContentValues after = new ContentValues();
3236f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ValuesDelta values = ValuesDelta.fromAfter(after);
3246f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3256f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertTrue("Expected empty", EntityModifier.isEmpty(values, kindPhone));
3266f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
3276f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3286f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testIsEmptyDirectFields() {
329b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
3306f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
3316f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
3326f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3336f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Test row that has type values, but core fields are empty
3347f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
3356f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
3366f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3376f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertTrue("Expected empty", EntityModifier.isEmpty(values, kindPhone));
3386f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3396f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Insert some data to trigger non-empty state
3406f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        values.put(Phone.NUMBER, TEST_PHONE);
3416f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3426f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertFalse("Expected non-empty", EntityModifier.isEmpty(values, kindPhone));
3436f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
3446f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3456f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testTrimEmptySingle() {
346b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
3476f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
3486f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
3496f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3506f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Test row that has type values, but core fields are empty
3517f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
3526c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.insertChild(state, kindPhone, typeHome);
3536f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3546f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build diff, expecting insert for data row and update enforcement
3556f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
3566f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
3576f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
3586f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
3596f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(0);
3606f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
3616f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3626f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
3636f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
3646f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(1);
3656f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
3666f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
3676f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
3686f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
3696f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(2);
3706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
3716f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3726f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
3736f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
3747f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Trim empty rows and try again, expecting delete of overall contact
3757f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        EntityModifier.trimEmpty(state, source);
3766f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
3776f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
3787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 1, diff.size());
3797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
3807f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
3817f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
3827f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
3837f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
3846f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
3856f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
386e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    public void testTrimEmptySpaces() {
387b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
388e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
389e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
390e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
391e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Test row that has type values, but values are spaces
392ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDelta state = EntityDeltaListTests.buildBeforeEntity(TEST_ID, VER_FIRST);
393e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
394e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        values.put(Phone.NUMBER, "   ");
395e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
396e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Build diff, expecting insert for data row and update enforcement
397ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
398ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
399ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationSuspended(),
400ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
401ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
402ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationDefault());
403e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
404e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Trim empty rows and try again, expecting delete of overall contact
405e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        EntityModifier.trimEmpty(state, source);
406ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
407ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
408ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildDelete(RawContacts.CONTENT_URI));
409e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    }
410e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
411e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    public void testTrimLeaveValid() {
412b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
413e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
414e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
415e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
416e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Test row that has type values with valid number
417ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDelta state = EntityDeltaListTests.buildBeforeEntity(TEST_ID, VER_FIRST);
418e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        final ValuesDelta values = EntityModifier.insertChild(state, kindPhone, typeHome);
419e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        values.put(Phone.NUMBER, TEST_PHONE);
420e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
421e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Build diff, expecting insert for data row and update enforcement
422ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
423ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
424ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationSuspended(),
425ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
426ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
427ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationDefault());
428e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
429e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        // Trim empty rows and try again, expecting no differences
430e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey        EntityModifier.trimEmpty(state, source);
431ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        EntityDeltaListTests.assertDiffPattern(state,
432ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildAssertVersion(VER_FIRST),
433ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationSuspended(),
434ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT,
435ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                        EntityDeltaListTests.buildDataInsert(values, TEST_ID)),
436ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann                EntityDeltaListTests.buildUpdateAggregationDefault());
437e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey    }
438e31dac84479a4c7b356edfc062a447cdfb5efc69Jeff Sharkey
4396f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testTrimEmptyUntouched() {
440b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
4416f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
4426c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
4436f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4446f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build "before" that has empty row
4457f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
4466f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ContentValues before = new ContentValues();
4476f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data._ID, TEST_ID);
4486f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
4496f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.addEntry(ValuesDelta.fromBefore(before));
4506f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4516f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build diff, expecting no changes
4526f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
4536f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4546f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
4556f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4566f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Try trimming existing empty, which we shouldn't touch
4577f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        EntityModifier.trimEmpty(state, source);
4586f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
4596f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4606f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
4616f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
4626f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4636f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    public void testTrimEmptyAfterUpdate() {
464b77be6d2ad06edfd8751f55043e4aa9fd9f36015Dmitri Plotnikov        final AccountType source = getAccountType();
4656f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
4666f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
4676f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4686f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build "before" that has row with some phone number
4696f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ContentValues before = new ContentValues();
4706f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data._ID, TEST_ID);
4716f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
4726f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(kindPhone.typeColumn, typeHome.rawValue);
4736f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        before.put(Phone.NUMBER, TEST_PHONE);
4747f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, before);
4756f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4766f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Build diff, expecting no changes
4776f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
4786f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4796f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
4806f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
4816f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Now update row by changing number to empty string, expecting single update
4826f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        final ValuesDelta child = state.getEntry(TEST_ID);
4836f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        child.put(Phone.NUMBER, "");
4846f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
4856f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
4866f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
4876f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
4886f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(0);
4896f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
4906f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
4916f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
4926f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
4936f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(1);
4946f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
4956f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
4966f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
4976f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
4986f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(2);
4996f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
5006f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5016f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
5026f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey
5036f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        // Now run trim, which should turn that update into delete
5047f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        EntityModifier.trimEmpty(state, source);
5057f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
5067f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5077f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 1, diff.size());
5087f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5097f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
5107f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
5117f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5127f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5137f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
5147f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5157f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimInsertEmpty() {
516a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
517a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
518a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
5196c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
5207f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5217f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Try creating a contact without any child entries
5227f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(null);
523ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
5247f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5257f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting single insert
5267f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
5277f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5283aba36cc373e82ca3a3331bb77bd1278d0afde06Dmitri Plotnikov        assertEquals("Unexpected operations", 2, diff.size());
5297f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5307f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
5317f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
5327f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5337f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5347f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5357f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Trim empty rows and try again, expecting no insert
536a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
5377f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
5387f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5397f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
5407f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
5417f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5427f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimInsertInsert() {
543a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
544a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
545a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
5467f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
5477f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5487f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Try creating a contact with single empty entry
5497f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(null);
5506c9b4b97752e415528279464b28560d389256783Daniel Lehmann        EntityModifier.insertChild(state, kindPhone, typeHome);
551ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
5527f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5537f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting two insert operations
5547f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
5557f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5563aba36cc373e82ca3a3331bb77bd1278d0afde06Dmitri Plotnikov        assertEquals("Unexpected operations", 3, diff.size());
5577f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5587f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
5597f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
5607f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
5617f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5627f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
5637f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(1);
5647f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_INSERT, oper.getType());
5657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
5667f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
5677f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5687f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Trim empty rows and try again, expecting silence
569a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
5707f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
5717f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
5727f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
5737f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
5747f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5757f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimUpdateRemain() {
576a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
577a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
578a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
5797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
5807f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5817f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build "before" with two phone numbers
5827f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ContentValues first = new ContentValues();
5837f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data._ID, TEST_ID);
5847f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
5857f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(kindPhone.typeColumn, typeHome.rawValue);
5867f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Phone.NUMBER, TEST_PHONE);
5877f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5887f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ContentValues second = new ContentValues();
5897f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(Data._ID, TEST_ID);
5907f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
5917f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(kindPhone.typeColumn, typeHome.rawValue);
5927f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        second.put(Phone.NUMBER, TEST_PHONE);
5937f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5947f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first, second);
595ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
5967f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
5977f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting no changes
5987f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
5997f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6007f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
6017f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6027f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now update row by changing number to empty string, expecting single update
6037f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ValuesDelta child = state.getEntry(TEST_ID);
6047f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        child.put(Phone.NUMBER, "");
6057f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
6067f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6077f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
6087f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6097f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6107f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6117f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6127f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6137f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6147f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(1);
6157f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
6167f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
6177f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6187f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6197f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(2);
6207f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6217f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6227f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6237f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6247f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now run trim, which should turn that update into delete
625a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
6266f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        diff.clear();
6276f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        state.buildDiff(diff);
6286f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
6296f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
6306f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6316f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6326f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6336f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
6346f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
6356f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(1);
6366f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
6376f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
6386f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
6396f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        {
6406f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            final ContentProviderOperation oper = diff.get(2);
6416f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6426f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6436f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey        }
6446f8d46b5fb96c2bead1317aae93a73fc89b093abJeff Sharkey    }
6457f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6467f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    public void testTrimUpdateUpdate() {
647a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
648a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountTypeManager accountTypes = getAccountTypes(accountType);
649a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
6507f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EditType typeHome = EntityModifier.getType(kindPhone, Phone.TYPE_HOME);
6517f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6527f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build "before" with two phone numbers
6537f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ContentValues first = new ContentValues();
6547f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data._ID, TEST_ID);
6557f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
6567f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(kindPhone.typeColumn, typeHome.rawValue);
6577f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        first.put(Phone.NUMBER, TEST_PHONE);
6587f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6597f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first);
660ca98444277723c60be83062cf5a25ec7ca1fdb34Daniel Lehmann        final EntityDeltaList set = EntityDeltaList.fromSingle(state);
6617f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6627f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Build diff, expecting no changes
6637f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ArrayList<ContentProviderOperation> diff = Lists.newArrayList();
6647f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6657f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 0, diff.size());
6667f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6677f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now update row by changing number to empty string, expecting single update
6687f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        final ValuesDelta child = state.getEntry(TEST_ID);
6697f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        child.put(Phone.NUMBER, "");
6707f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
6717f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6727f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 3, diff.size());
6737f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6747f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6757f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6767f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6777f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6787f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6797f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(1);
6807f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_UPDATE, oper.getType());
6817f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri());
6827f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6837f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6847f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(2);
6857f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType());
6867f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6877f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6887f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey
6897f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        // Now run trim, which should turn into deleting the whole contact
690a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.trimEmpty(set, accountTypes);
6917f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        diff.clear();
6927f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        state.buildDiff(diff);
6937f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        assertEquals("Unexpected operations", 1, diff.size());
6947f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        {
6957f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            final ContentProviderOperation oper = diff.get(0);
6967f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect type", TYPE_DELETE, oper.getType());
6977f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey            assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri());
6987f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey        }
6997f86847eddbec5dff4d87ac9243d839593582e42Jeff Sharkey    }
70016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
70116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasExistingName() {
702a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
70316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
70416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Build "before" name
70516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final ContentValues first = new ContentValues();
70616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data._ID, TEST_ID);
70716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
70816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(StructuredName.GIVEN_NAME, TEST_NAME);
70916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
71016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Parse extras, making sure we keep single name
71116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first);
71216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
71316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.NAME, TEST_NAME2);
714a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
71516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
71616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int nameCount = state.getMimeEntriesCount(StructuredName.CONTENT_ITEM_TYPE, true);
71716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        assertEquals("Unexpected names", 1, nameCount);
71816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
71916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
72016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasIgnoreLimit() {
721a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
72216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
72316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Build "before" IM
72416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final ContentValues first = new ContentValues();
72516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data._ID, TEST_ID);
72616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
72716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        first.put(Im.DATA, TEST_IM);
72816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
72916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID, first);
73016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int beforeCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
73116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
732a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        // We should ignore data that doesn't fit account type rules, since account type
73316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // only allows single Im
73416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
73516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putInt(Insert.IM_PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
73616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.IM_HANDLE, TEST_IM);
737a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
73816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
73916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int afterCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size();
740a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        assertEquals("Broke account type rules", beforeCount, afterCount);
74116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
74216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
74316c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasIgnoreUnhandled() {
744a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
74516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
74616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
747a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        // We should silently ignore types unsupported by account type
74816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
74916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.POSTAL, TEST_POSTAL);
750a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
75116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
752a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        assertNull("Broke accoun type rules",
753a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov                state.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE));
75416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
75516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
75616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    public void testParseExtrasJobTitle() {
757a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        final AccountType accountType = getAccountType();
75816c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final EntityDelta state = getEntity(TEST_ID);
75916c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
76016c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        // Make sure that we create partial Organizations
76116c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final Bundle extras = new Bundle();
76216c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        extras.putString(Insert.JOB_TITLE, TEST_NAME);
763a07fa5f37031e4c5cd2933de02d2db41ec153e2bDmitri Plotnikov        EntityModifier.parseExtras(mContext, accountType, state, extras);
76416c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey
76516c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        final int count = state.getMimeEntries(Organization.CONTENT_ITEM_TYPE).size();
76616c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey        assertEquals("Expected to create organization", 1, count);
76716c364a557d619a0396ed35249478dcf2c1ffba5Jeff Sharkey    }
768d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
769d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateWithDisplayNameFromGoogleToExchange1() {
770d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
771d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
772d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
773d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
774d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContactsMockContext context = new ContactsMockContext(getContext());
775d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
776d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
777d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
778d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
779d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.PREFIX, "prefix");
780d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.GIVEN_NAME, "given");
781d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.MIDDLE_NAME, "middle");
782d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.FAMILY_NAME, "family");
783d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.SUFFIX, "suffix");
784d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "PHONETIC_FAMILY");
785d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "PHONETIC_MIDDLE");
786d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "PHONETIC_GIVEN");
787d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
788d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
789d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
790d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateStructuredName(context, oldState, newState, kind);
791d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
792d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());
793d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
794d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues output = list.get(0).getAfter();
795d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("prefix", output.getAsString(StructuredName.PREFIX));
796d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("given", output.getAsString(StructuredName.GIVEN_NAME));
797d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("middle", output.getAsString(StructuredName.MIDDLE_NAME));
798d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("family", output.getAsString(StructuredName.FAMILY_NAME));
799d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("suffix", output.getAsString(StructuredName.SUFFIX));
800d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Phonetic middle name isn't supported by Exchange.
801d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("PHONETIC_FAMILY", output.getAsString(StructuredName.PHONETIC_FAMILY_NAME));
802d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("PHONETIC_GIVEN", output.getAsString(StructuredName.PHONETIC_GIVEN_NAME));
803d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
804d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
805d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateWithDisplayNameFromGoogleToExchange2() {
806d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
807d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
808d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
809d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
810d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContactsMockContext context = new ContactsMockContext(getContext());
811d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        MockContentProvider provider = context.getContactsProvider();
812d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
813d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        String inputDisplayName = "prefix given middle family suffix";
814d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // The method will ask the provider to split/join StructuredName.
815d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        Uri uriForBuildDisplayName =
816d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                ContactsContract.AUTHORITY_URI
817d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .buildUpon()
818d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendPath("complete_name")
819d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendQueryParameter(StructuredName.DISPLAY_NAME, inputDisplayName)
820d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .build();
821d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        provider.expectQuery(uriForBuildDisplayName)
822d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                .returnRow("prefix", "given", "middle", "family", "suffix")
823d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                .withProjection(StructuredName.PREFIX, StructuredName.GIVEN_NAME,
824d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        StructuredName.MIDDLE_NAME, StructuredName.FAMILY_NAME,
825d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        StructuredName.SUFFIX);
826d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
827d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
828d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
829d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
830d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.DISPLAY_NAME, inputDisplayName);
831d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
832d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
833d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
834d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateStructuredName(context, oldState, newState, kind);
835d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
836d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());
837d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
838d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
839d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("prefix", outputValues.getAsString(StructuredName.PREFIX));
840d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("given", outputValues.getAsString(StructuredName.GIVEN_NAME));
841d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("middle", outputValues.getAsString(StructuredName.MIDDLE_NAME));
842d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("family", outputValues.getAsString(StructuredName.FAMILY_NAME));
843d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("suffix", outputValues.getAsString(StructuredName.SUFFIX));
844d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
845d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
846d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateWithStructuredNameFromExchangeToGoogle() {
847d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new ExchangeAccountType(getContext(), "");
848d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new GoogleAccountType(getContext(), "");
849d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE);
850d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
851d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContactsMockContext context = new ContactsMockContext(getContext());
852d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        MockContentProvider provider = context.getContactsProvider();
853d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
854d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // The method will ask the provider to split/join StructuredName.
855d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        Uri uriForBuildDisplayName =
856d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                ContactsContract.AUTHORITY_URI
857d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .buildUpon()
858d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendPath("complete_name")
859d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendQueryParameter(StructuredName.PREFIX, "prefix")
860d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendQueryParameter(StructuredName.GIVEN_NAME, "given")
861d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendQueryParameter(StructuredName.MIDDLE_NAME, "middle")
862d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendQueryParameter(StructuredName.FAMILY_NAME, "family")
863d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .appendQueryParameter(StructuredName.SUFFIX, "suffix")
864d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                        .build();
865d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        provider.expectQuery(uriForBuildDisplayName)
866d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                .returnRow("prefix given middle family suffix")
867d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                .withProjection(StructuredName.DISPLAY_NAME);
868d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
869d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
870d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
871d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
872d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.PREFIX, "prefix");
873d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.GIVEN_NAME, "given");
874d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.MIDDLE_NAME, "middle");
875d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.FAMILY_NAME, "family");
876d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredName.SUFFIX, "suffix");
877d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
878d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
879d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
880d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateStructuredName(context, oldState, newState, kind);
881d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
882d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE);
883d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
884d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());
885d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
886d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("prefix given middle family suffix",
887d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                outputValues.getAsString(StructuredName.DISPLAY_NAME));
888d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
889d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
890d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigratePostalFromGoogleToExchange() {
891d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
892d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
893d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
894d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
895d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
896d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
897d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
898d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredPostal.FORMATTED_ADDRESS, "formatted_address");
899d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
900d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
901d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
902d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migratePostal(oldState, newState, kind);
903d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
904d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
905d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
906d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());
907d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
908d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // FORMATTED_ADDRESS isn't supported by Exchange.
909d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNull(outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS));
910d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("formatted_address", outputValues.getAsString(StructuredPostal.STREET));
911d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
912d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
913d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigratePostalFromExchangeToGoogle() {
914d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new ExchangeAccountType(getContext(), "");
915d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new GoogleAccountType(getContext(), "");
916d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE);
917d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
918d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
919d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
920d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE);
921d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredPostal.COUNTRY, "country");
922d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredPostal.POSTCODE, "postcode");
923d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredPostal.REGION, "region");
924d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredPostal.CITY, "city");
925d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(StructuredPostal.STREET, "street");
926d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
927d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
928d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
929d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migratePostal(oldState, newState, kind);
930d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
931d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE);
932d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
933d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());
934d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
935d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
936d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Check FORMATTED_ADDRESS contains all info.
937d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        String formattedAddress = outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS);
938d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(formattedAddress);
939d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertTrue(formattedAddress.contains("country"));
940d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertTrue(formattedAddress.contains("postcode"));
941d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertTrue(formattedAddress.contains("region"));
942d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertTrue(formattedAddress.contains("postcode"));
943d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertTrue(formattedAddress.contains("city"));
944d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertTrue(formattedAddress.contains("street"));
945d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
946d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
947d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateEventFromGoogleToExchange1() {
948d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        testMigrateEventCommon(new GoogleAccountType(getContext(), ""),
949d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                new ExchangeAccountType(getContext(), ""));
950d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
951d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
952d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateEventFromExchangeToGoogle() {
953d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        testMigrateEventCommon(new ExchangeAccountType(getContext(), ""),
954d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa                new GoogleAccountType(getContext(), ""));
955d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
956d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
957d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    private void testMigrateEventCommon(AccountType oldAccountType, AccountType newAccountType) {
958d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
959d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
960d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
961d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
962d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
963d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Event.START_DATE, "1972-02-08");
964d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
965d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
966d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
967d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
968d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateEvent(oldState, newState, kind, 1990);
969d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
970d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
971d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
972d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());  // Anniversary should be dropped.
973d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
974d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
975d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("1972-02-08", outputValues.getAsString(Event.START_DATE));
976d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue());
977d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
978d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
979d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateEventFromGoogleToExchange2() {
980d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
981d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
982d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE);
983d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
984d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
985d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
986d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
987d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // No year format is not supported by Exchange.
988d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Event.START_DATE, "--06-01");
989d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY);
990d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
991d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
992d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE);
993d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Event.START_DATE, "1980-08-02");
994d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Anniversary is not supported by Exchange
995d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY);
996d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
997d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
998d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
999d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateEvent(oldState, newState, kind, 1990);
1000d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1001d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE);
1002d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
1003d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());  // Anniversary should be dropped.
1004d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
1005d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1006d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Default year should be used.
1007d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("1990-06-01", outputValues.getAsString(Event.START_DATE));
1008d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue());
1009d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
1010d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1011d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateEmailFromGoogleToExchange() {
1012d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
1013d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
1014d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(Email.CONTENT_ITEM_TYPE);
1015d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1016d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
1017d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
1018d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
1019d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.TYPE, Email.TYPE_CUSTOM);
1020d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.LABEL, "custom_type");
1021d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.ADDRESS, "address1");
1022d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1023d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1024d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
1025d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.TYPE, Email.TYPE_HOME);
1026d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.ADDRESS, "address2");
1027d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1028d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1029d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
1030d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.TYPE, Email.TYPE_WORK);
1031d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.ADDRESS, "address3");
1032d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1033d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Exchange can have up to 3 email entries. This 4th entry should be dropped.
1034d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1035d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
1036d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.TYPE, Email.TYPE_OTHER);
1037d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Email.ADDRESS, "address4");
1038d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1039d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1040d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
1041d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
1042d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1043d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(Email.CONTENT_ITEM_TYPE);
1044d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
1045d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(3, list.size());
1046d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1047d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
1048d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Email.TYPE_CUSTOM, outputValues.getAsInteger(Email.TYPE).intValue());
1049d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("custom_type", outputValues.getAsString(Email.LABEL));
1050d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("address1", outputValues.getAsString(Email.ADDRESS));
1051d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1052d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(1).getAfter();
1053d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Email.TYPE_HOME, outputValues.getAsInteger(Email.TYPE).intValue());
1054d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("address2", outputValues.getAsString(Email.ADDRESS));
1055d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1056d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(2).getAfter();
1057d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Email.TYPE_WORK, outputValues.getAsInteger(Email.TYPE).intValue());
1058d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("address3", outputValues.getAsString(Email.ADDRESS));
1059d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
1060d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1061d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateImFromGoogleToExchange() {
1062d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
1063d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
1064d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(Im.CONTENT_ITEM_TYPE);
1065d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1066d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
1067d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
1068d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
1069d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Exchange doesn't support TYPE_HOME
1070d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.TYPE, Im.TYPE_HOME);
1071d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_JABBER);
1072d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.DATA, "im1");
1073d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1074d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1075d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1076d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
1077d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Exchange doesn't support TYPE_WORK
1078d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.TYPE, Im.TYPE_WORK);
1079d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_YAHOO);
1080d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.DATA, "im2");
1081d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1082d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1083d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1084d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
1085d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.TYPE, Im.TYPE_OTHER);
1086d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_CUSTOM);
1087d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.CUSTOM_PROTOCOL, "custom_protocol");
1088d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.DATA, "im3");
1089d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1090d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1091d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // Exchange can have up to 3 IM entries. This 4th entry should be dropped.
1092d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1093d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE);
1094d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.TYPE, Im.TYPE_OTHER);
1095d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK);
1096d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Im.DATA, "im4");
1097d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1098d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1099d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
1100d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
1101d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1102d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(Im.CONTENT_ITEM_TYPE);
1103d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
1104d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(3, list.size());
1105d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1106d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(kind.defaultValues.getAsInteger(Im.TYPE));
1107d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1108d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        int defaultType = kind.defaultValues.getAsInteger(Im.TYPE);
1109d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1110d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
1111d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        // HOME should become default type.
1112d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
1113d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Im.PROTOCOL_JABBER, outputValues.getAsInteger(Im.PROTOCOL).intValue());
1114d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("im1", outputValues.getAsString(Im.DATA));
1115d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1116d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(1).getAfter();
1117d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
1118d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Im.PROTOCOL_YAHOO, outputValues.getAsInteger(Im.PROTOCOL).intValue());
1119d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("im2", outputValues.getAsString(Im.DATA));
1120d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1121d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(2).getAfter();
1122d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue());
1123d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Im.PROTOCOL_CUSTOM, outputValues.getAsInteger(Im.PROTOCOL).intValue());
1124d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("custom_protocol", outputValues.getAsString(Im.CUSTOM_PROTOCOL));
1125d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("im3", outputValues.getAsString(Im.DATA));
1126d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
1127d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1128d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigratePhoneFromGoogleToExchange() {
1129d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
1130d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
1131d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE);
1132d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
11330070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // Create 5 numbers.
11340070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "1" -- HOME
11350070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "2" -- WORK
11360070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "3" -- CUSTOM
11370070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "4" -- WORK
11380070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "5" -- WORK_MOBILE
11390070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // Then we convert it to Exchange account type.
11400070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "1" -- HOME
11410070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "2" -- WORK
11420070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "3" -- Because CUSTOM is not supported, it'll be changed to the default, MOBILE
11430070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "4" -- WORK
11440070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "5" -- WORK_MOBILE not suppoted again, so will be MOBILE.
11450070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // But then, Exchange doesn't support multiple MOBILE numbers, so "5" will be removed.
11460070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // i.e. the result will be:
11470070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "1" -- HOME
11480070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "2" -- WORK
11490070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "3" -- MOBILE
11500070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // - "4" -- WORK
11510070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki
1152d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
1153d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
1154d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
1155d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.TYPE, Phone.TYPE_HOME);
1156d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.NUMBER, "1");
1157d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1158d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1159d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
11600070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK);
1161d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.NUMBER, "2");
1162d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1163d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1164d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
11650070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        // Exchange doesn't support this type. Default to MOBILE
1166d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.TYPE, Phone.TYPE_CUSTOM);
1167d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.LABEL, "custom_type");
1168d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.NUMBER, "3");
1169d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1170d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1171d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
1172d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK);
1173d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.NUMBER, "4");
1174d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1175d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues = new ContentValues();
1176d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1177d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
1178d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK_MOBILE);
1179d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Phone.NUMBER, "5");
1180d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1181d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1182d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
1183d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateGenericWithTypeColumn(oldState, newState, kind);
1184d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1185d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
1186d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
1187d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(4, list.size());
1188d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
11890070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        int defaultType = Phone.TYPE_MOBILE;
1190d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1191d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
1192d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Phone.TYPE_HOME, outputValues.getAsInteger(Phone.TYPE).intValue());
1193d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("1", outputValues.getAsString(Phone.NUMBER));
1194d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(1).getAfter();
11950070e986c3085de912b41a1b14a60ff7d2e76b5cMakoto Onuki        assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue());
1196d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("2", outputValues.getAsString(Phone.NUMBER));
1197d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(2).getAfter();
1198d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(defaultType, outputValues.getAsInteger(Phone.TYPE).intValue());
1199d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNull(outputValues.getAsInteger(Phone.LABEL));
1200d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("3", outputValues.getAsString(Phone.NUMBER));
1201d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        outputValues = list.get(3).getAfter();
1202d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue());
1203d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("4", outputValues.getAsString(Phone.NUMBER));
1204d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
1205d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1206d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    public void testMigrateOrganizationFromGoogleToExchange() {
1207d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType oldAccountType = new GoogleAccountType(getContext(), "");
1208d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        AccountType newAccountType = new ExchangeAccountType(getContext(), "");
1209d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        DataKind kind = newAccountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE);
1210d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1211d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta oldState = new EntityDelta();
1212d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues mockNameValues = new ContentValues();
1213d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE);
1214d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Organization.COMPANY, "company1");
1215d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        mockNameValues.put(Organization.DEPARTMENT, "department1");
1216d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        oldState.addEntry(ValuesDelta.fromAfter(mockNameValues));
1217d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1218d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityDelta newState = new EntityDelta();
1219d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        EntityModifier.migrateGenericWithoutTypeColumn(oldState, newState, kind);
1220d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1221d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        List<ValuesDelta> list = newState.getMimeEntries(Organization.CONTENT_ITEM_TYPE);
1222d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertNotNull(list);
1223d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals(1, list.size());
1224d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa
1225d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        ContentValues outputValues = list.get(0).getAfter();
1226d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("company1", outputValues.getAsString(Organization.COMPANY));
1227d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa        assertEquals("department1", outputValues.getAsString(Organization.DEPARTMENT));
1228d37a891cb44cd17083c06d7be693c469403d16dfDaisuke Miyakawa    }
122907c2e41b5ce7abeb9dd14e5d700a8fb928723330Jeff Sharkey}
1230