| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.contacts; |
| |
| import static android.content.ContentProviderOperation.TYPE_DELETE; |
| import static android.content.ContentProviderOperation.TYPE_INSERT; |
| import static android.content.ContentProviderOperation.TYPE_UPDATE; |
| |
| import android.content.ContentProviderOperation; |
| import android.content.ContentValues; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.provider.ContactsContract; |
| import android.provider.ContactsContract.CommonDataKinds.Email; |
| import android.provider.ContactsContract.CommonDataKinds.Event; |
| import android.provider.ContactsContract.CommonDataKinds.Im; |
| import android.provider.ContactsContract.CommonDataKinds.Organization; |
| import android.provider.ContactsContract.CommonDataKinds.Phone; |
| import android.provider.ContactsContract.CommonDataKinds.StructuredName; |
| import android.provider.ContactsContract.CommonDataKinds.StructuredPostal; |
| import android.provider.ContactsContract.Data; |
| import android.provider.ContactsContract.Intents.Insert; |
| import android.provider.ContactsContract.RawContacts; |
| import android.test.AndroidTestCase; |
| import android.test.suitebuilder.annotation.LargeTest; |
| |
| import com.android.contacts.common.model.AccountTypeManager; |
| import com.android.contacts.model.RawContact; |
| import com.android.contacts.model.RawContactDelta; |
| import com.android.contacts.common.model.ValuesDelta; |
| import com.android.contacts.model.RawContactDeltaList; |
| import com.android.contacts.model.RawContactModifier; |
| import com.android.contacts.common.model.account.AccountType; |
| import com.android.contacts.common.model.account.AccountType.EditType; |
| import com.android.contacts.common.model.account.ExchangeAccountType; |
| import com.android.contacts.common.model.account.GoogleAccountType; |
| import com.android.contacts.common.model.dataitem.DataKind; |
| import com.android.contacts.common.test.mocks.ContactsMockContext; |
| import com.android.contacts.tests.mocks.MockAccountTypeManager; |
| import com.android.contacts.common.test.mocks.MockContentProvider; |
| import com.google.common.collect.Lists; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * Tests for {@link RawContactModifier} to verify that {@link AccountType} |
| * constraints are being enforced correctly. |
| */ |
| @LargeTest |
| public class RawContactModifierTests extends AndroidTestCase { |
| public static final String TAG = "EntityModifierTests"; |
| |
| public static final long VER_FIRST = 100; |
| |
| private static final long TEST_ID = 4; |
| private static final String TEST_PHONE = "218-555-1212"; |
| private static final String TEST_NAME = "Adam Young"; |
| private static final String TEST_NAME2 = "Breanne Duren"; |
| private static final String TEST_IM = "example@example.com"; |
| private static final String TEST_POSTAL = "1600 Amphitheatre Parkway"; |
| |
| private static final String TEST_ACCOUNT_NAME = "unittest@example.com"; |
| private static final String TEST_ACCOUNT_TYPE = "com.example.unittest"; |
| |
| private static final String EXCHANGE_ACCT_TYPE = "com.android.exchange"; |
| |
| @Override |
| public void setUp() { |
| mContext = getContext(); |
| } |
| |
| public static class MockContactsSource extends AccountType { |
| |
| MockContactsSource() { |
| try { |
| this.accountType = TEST_ACCOUNT_TYPE; |
| |
| final DataKind nameKind = new DataKind(StructuredName.CONTENT_ITEM_TYPE, |
| R.string.nameLabelsGroup, -1, true); |
| nameKind.typeOverallMax = 1; |
| addKind(nameKind); |
| |
| // Phone allows maximum 2 home, 1 work, and unlimited other, with |
| // constraint of 5 numbers maximum. |
| final DataKind phoneKind = new DataKind( |
| Phone.CONTENT_ITEM_TYPE, -1, 10, true); |
| |
| phoneKind.typeOverallMax = 5; |
| phoneKind.typeColumn = Phone.TYPE; |
| phoneKind.typeList = Lists.newArrayList(); |
| phoneKind.typeList.add(new EditType(Phone.TYPE_HOME, -1).setSpecificMax(2)); |
| phoneKind.typeList.add(new EditType(Phone.TYPE_WORK, -1).setSpecificMax(1)); |
| phoneKind.typeList.add(new EditType(Phone.TYPE_FAX_WORK, -1).setSecondary(true)); |
| phoneKind.typeList.add(new EditType(Phone.TYPE_OTHER, -1)); |
| |
| phoneKind.fieldList = Lists.newArrayList(); |
| phoneKind.fieldList.add(new EditField(Phone.NUMBER, -1, -1)); |
| phoneKind.fieldList.add(new EditField(Phone.LABEL, -1, -1)); |
| |
| addKind(phoneKind); |
| |
| // Email is unlimited |
| final DataKind emailKind = new DataKind(Email.CONTENT_ITEM_TYPE, -1, 10, true); |
| emailKind.typeOverallMax = -1; |
| emailKind.fieldList = Lists.newArrayList(); |
| emailKind.fieldList.add(new EditField(Email.DATA, -1, -1)); |
| addKind(emailKind); |
| |
| // IM is only one |
| final DataKind imKind = new DataKind(Im.CONTENT_ITEM_TYPE, -1, 10, true); |
| imKind.typeOverallMax = 1; |
| imKind.fieldList = Lists.newArrayList(); |
| imKind.fieldList.add(new EditField(Im.DATA, -1, -1)); |
| addKind(imKind); |
| |
| // Organization is only one |
| final DataKind orgKind = new DataKind(Organization.CONTENT_ITEM_TYPE, -1, 10, true); |
| orgKind.typeOverallMax = 1; |
| orgKind.fieldList = Lists.newArrayList(); |
| orgKind.fieldList.add(new EditField(Organization.COMPANY, -1, -1)); |
| orgKind.fieldList.add(new EditField(Organization.TITLE, -1, -1)); |
| addKind(orgKind); |
| } catch (DefinitionException e) { |
| throw new RuntimeException(e); |
| } |
| } |
| |
| @Override |
| public boolean isGroupMembershipEditable() { |
| return false; |
| } |
| |
| @Override |
| public boolean areContactsWritable() { |
| return true; |
| } |
| } |
| |
| /** |
| * Build a {@link AccountType} that has various odd constraints for |
| * testing purposes. |
| */ |
| protected AccountType getAccountType() { |
| return new MockContactsSource(); |
| } |
| |
| /** |
| * Build {@link AccountTypeManager} instance. |
| */ |
| protected AccountTypeManager getAccountTypes(AccountType... types) { |
| return new MockAccountTypeManager(types, null); |
| } |
| |
| /** |
| * Build an {@link RawContact} with the requested set of phone numbers. |
| */ |
| protected RawContactDelta getRawContact(Long existingId, ContentValues... entries) { |
| final ContentValues contact = new ContentValues(); |
| if (existingId != null) { |
| contact.put(RawContacts._ID, existingId); |
| } |
| contact.put(RawContacts.ACCOUNT_NAME, TEST_ACCOUNT_NAME); |
| contact.put(RawContacts.ACCOUNT_TYPE, TEST_ACCOUNT_TYPE); |
| |
| final RawContact before = new RawContact(contact); |
| for (ContentValues values : entries) { |
| before.addDataItemValues(values); |
| } |
| return RawContactDelta.fromBefore(before); |
| } |
| |
| /** |
| * Assert this {@link List} contains the given {@link Object}. |
| */ |
| protected void assertContains(List<?> list, Object object) { |
| assertTrue("Missing expected value", list.contains(object)); |
| } |
| |
| /** |
| * Assert this {@link List} does not contain the given {@link Object}. |
| */ |
| protected void assertNotContains(List<?> list, Object object) { |
| assertFalse("Contained unexpected value", list.contains(object)); |
| } |
| |
| /** |
| * Insert various rows to test |
| * {@link RawContactModifier#getValidTypes(RawContactDelta, DataKind, EditType)} |
| */ |
| public void testValidTypes() { |
| // Build a source and pull specific types |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| final EditType typeWork = RawContactModifier.getType(kindPhone, Phone.TYPE_WORK); |
| final EditType typeOther = RawContactModifier.getType(kindPhone, Phone.TYPE_OTHER); |
| |
| List<EditType> validTypes; |
| |
| // Add first home, first work |
| final RawContactDelta state = getRawContact(TEST_ID); |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| RawContactModifier.insertChild(state, kindPhone, typeWork); |
| |
| // Expecting home, other |
| validTypes = RawContactModifier.getValidTypes(state, kindPhone, null); |
| assertContains(validTypes, typeHome); |
| assertNotContains(validTypes, typeWork); |
| assertContains(validTypes, typeOther); |
| |
| // Add second home |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| |
| // Expecting other |
| validTypes = RawContactModifier.getValidTypes(state, kindPhone, null); |
| assertNotContains(validTypes, typeHome); |
| assertNotContains(validTypes, typeWork); |
| assertContains(validTypes, typeOther); |
| |
| // Add third and fourth home (invalid, but possible) |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| |
| // Expecting none |
| validTypes = RawContactModifier.getValidTypes(state, kindPhone, null); |
| assertNotContains(validTypes, typeHome); |
| assertNotContains(validTypes, typeWork); |
| assertNotContains(validTypes, typeOther); |
| } |
| |
| /** |
| * Test {@link RawContactModifier#canInsert(RawContactDelta, DataKind)} by |
| * inserting various rows. |
| */ |
| public void testCanInsert() { |
| // Build a source and pull specific types |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| final EditType typeWork = RawContactModifier.getType(kindPhone, Phone.TYPE_WORK); |
| final EditType typeOther = RawContactModifier.getType(kindPhone, Phone.TYPE_OTHER); |
| |
| // Add first home, first work |
| final RawContactDelta state = getRawContact(TEST_ID); |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| RawContactModifier.insertChild(state, kindPhone, typeWork); |
| assertTrue("Unable to insert", RawContactModifier.canInsert(state, kindPhone)); |
| |
| // Add two other, which puts us just under "5" overall limit |
| RawContactModifier.insertChild(state, kindPhone, typeOther); |
| RawContactModifier.insertChild(state, kindPhone, typeOther); |
| assertTrue("Unable to insert", RawContactModifier.canInsert(state, kindPhone)); |
| |
| // Add second home, which should push to snug limit |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| assertFalse("Able to insert", RawContactModifier.canInsert(state, kindPhone)); |
| } |
| |
| /** |
| * Test |
| * {@link RawContactModifier#getBestValidType(RawContactDelta, DataKind, boolean, int)} |
| * by asserting expected best options in various states. |
| */ |
| public void testBestValidType() { |
| // Build a source and pull specific types |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| final EditType typeWork = RawContactModifier.getType(kindPhone, Phone.TYPE_WORK); |
| final EditType typeFaxWork = RawContactModifier.getType(kindPhone, Phone.TYPE_FAX_WORK); |
| final EditType typeOther = RawContactModifier.getType(kindPhone, Phone.TYPE_OTHER); |
| |
| EditType suggested; |
| |
| // Default suggestion should be home |
| final RawContactDelta state = getRawContact(TEST_ID); |
| suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE); |
| assertEquals("Unexpected suggestion", typeHome, suggested); |
| |
| // Add first home, should now suggest work |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE); |
| assertEquals("Unexpected suggestion", typeWork, suggested); |
| |
| // Add work fax, should still suggest work |
| RawContactModifier.insertChild(state, kindPhone, typeFaxWork); |
| suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE); |
| assertEquals("Unexpected suggestion", typeWork, suggested); |
| |
| // Add other, should still suggest work |
| RawContactModifier.insertChild(state, kindPhone, typeOther); |
| suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE); |
| assertEquals("Unexpected suggestion", typeWork, suggested); |
| |
| // Add work, now should suggest other |
| RawContactModifier.insertChild(state, kindPhone, typeWork); |
| suggested = RawContactModifier.getBestValidType(state, kindPhone, false, Integer.MIN_VALUE); |
| assertEquals("Unexpected suggestion", typeOther, suggested); |
| } |
| |
| public void testIsEmptyEmpty() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| |
| // Test entirely empty row |
| final ContentValues after = new ContentValues(); |
| final ValuesDelta values = ValuesDelta.fromAfter(after); |
| |
| assertTrue("Expected empty", RawContactModifier.isEmpty(values, kindPhone)); |
| } |
| |
| public void testIsEmptyDirectFields() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Test row that has type values, but core fields are empty |
| final RawContactDelta state = getRawContact(TEST_ID); |
| final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome); |
| |
| assertTrue("Expected empty", RawContactModifier.isEmpty(values, kindPhone)); |
| |
| // Insert some data to trigger non-empty state |
| values.put(Phone.NUMBER, TEST_PHONE); |
| |
| assertFalse("Expected non-empty", RawContactModifier.isEmpty(values, kindPhone)); |
| } |
| |
| public void testTrimEmptySingle() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Test row that has type values, but core fields are empty |
| final RawContactDelta state = getRawContact(TEST_ID); |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| |
| // Build diff, expecting insert for data row and update enforcement |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 3, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(1); |
| assertEquals("Incorrect type", TYPE_INSERT, oper.getType()); |
| assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(2); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| |
| // Trim empty rows and try again, expecting delete of overall contact |
| RawContactModifier.trimEmpty(state, source); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 1, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Incorrect type", TYPE_DELETE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| } |
| |
| public void testTrimEmptySpaces() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Test row that has type values, but values are spaces |
| final RawContactDelta state = RawContactDeltaListTests.buildBeforeEntity(mContext, TEST_ID, |
| VER_FIRST); |
| final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome); |
| values.put(Phone.NUMBER, " "); |
| |
| // Build diff, expecting insert for data row and update enforcement |
| RawContactDeltaListTests.assertDiffPattern(state, |
| RawContactDeltaListTests.buildAssertVersion(VER_FIRST), |
| RawContactDeltaListTests.buildUpdateAggregationSuspended(), |
| RawContactDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT, |
| RawContactDeltaListTests.buildDataInsert(values, TEST_ID)), |
| RawContactDeltaListTests.buildUpdateAggregationDefault()); |
| |
| // Trim empty rows and try again, expecting delete of overall contact |
| RawContactModifier.trimEmpty(state, source); |
| RawContactDeltaListTests.assertDiffPattern(state, |
| RawContactDeltaListTests.buildAssertVersion(VER_FIRST), |
| RawContactDeltaListTests.buildDelete(RawContacts.CONTENT_URI)); |
| } |
| |
| public void testTrimLeaveValid() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Test row that has type values with valid number |
| final RawContactDelta state = RawContactDeltaListTests.buildBeforeEntity(mContext, TEST_ID, |
| VER_FIRST); |
| final ValuesDelta values = RawContactModifier.insertChild(state, kindPhone, typeHome); |
| values.put(Phone.NUMBER, TEST_PHONE); |
| |
| // Build diff, expecting insert for data row and update enforcement |
| RawContactDeltaListTests.assertDiffPattern(state, |
| RawContactDeltaListTests.buildAssertVersion(VER_FIRST), |
| RawContactDeltaListTests.buildUpdateAggregationSuspended(), |
| RawContactDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT, |
| RawContactDeltaListTests.buildDataInsert(values, TEST_ID)), |
| RawContactDeltaListTests.buildUpdateAggregationDefault()); |
| |
| // Trim empty rows and try again, expecting no differences |
| RawContactModifier.trimEmpty(state, source); |
| RawContactDeltaListTests.assertDiffPattern(state, |
| RawContactDeltaListTests.buildAssertVersion(VER_FIRST), |
| RawContactDeltaListTests.buildUpdateAggregationSuspended(), |
| RawContactDeltaListTests.buildOper(Data.CONTENT_URI, TYPE_INSERT, |
| RawContactDeltaListTests.buildDataInsert(values, TEST_ID)), |
| RawContactDeltaListTests.buildUpdateAggregationDefault()); |
| } |
| |
| public void testTrimEmptyUntouched() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Build "before" that has empty row |
| final RawContactDelta state = getRawContact(TEST_ID); |
| final ContentValues before = new ContentValues(); |
| before.put(Data._ID, TEST_ID); |
| before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| state.addEntry(ValuesDelta.fromBefore(before)); |
| |
| // Build diff, expecting no changes |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| |
| // Try trimming existing empty, which we shouldn't touch |
| RawContactModifier.trimEmpty(state, source); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| } |
| |
| public void testTrimEmptyAfterUpdate() { |
| final AccountType source = getAccountType(); |
| final DataKind kindPhone = source.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Build "before" that has row with some phone number |
| final ContentValues before = new ContentValues(); |
| before.put(Data._ID, TEST_ID); |
| before.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| before.put(kindPhone.typeColumn, typeHome.rawValue); |
| before.put(Phone.NUMBER, TEST_PHONE); |
| final RawContactDelta state = getRawContact(TEST_ID, before); |
| |
| // Build diff, expecting no changes |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| |
| // Now update row by changing number to empty string, expecting single update |
| final ValuesDelta child = state.getEntry(TEST_ID); |
| child.put(Phone.NUMBER, ""); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 3, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(1); |
| assertEquals("Incorrect type", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(2); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| |
| // Now run trim, which should turn that update into delete |
| RawContactModifier.trimEmpty(state, source); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 1, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Incorrect type", TYPE_DELETE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| } |
| |
| public void testTrimInsertEmpty() { |
| final AccountType accountType = getAccountType(); |
| final AccountTypeManager accountTypes = getAccountTypes(accountType); |
| final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Try creating a contact without any child entries |
| final RawContactDelta state = getRawContact(null); |
| final RawContactDeltaList set = new RawContactDeltaList(); |
| set.add(state); |
| |
| |
| // Build diff, expecting single insert |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 2, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Incorrect type", TYPE_INSERT, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| |
| // Trim empty rows and try again, expecting no insert |
| RawContactModifier.trimEmpty(set, accountTypes); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| } |
| |
| public void testTrimInsertInsert() { |
| final AccountType accountType = getAccountType(); |
| final AccountTypeManager accountTypes = getAccountTypes(accountType); |
| final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Try creating a contact with single empty entry |
| final RawContactDelta state = getRawContact(null); |
| RawContactModifier.insertChild(state, kindPhone, typeHome); |
| final RawContactDeltaList set = new RawContactDeltaList(); |
| set.add(state); |
| |
| // Build diff, expecting two insert operations |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 3, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Incorrect type", TYPE_INSERT, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(1); |
| assertEquals("Incorrect type", TYPE_INSERT, oper.getType()); |
| assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri()); |
| } |
| |
| // Trim empty rows and try again, expecting silence |
| RawContactModifier.trimEmpty(set, accountTypes); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| } |
| |
| public void testTrimUpdateRemain() { |
| final AccountType accountType = getAccountType(); |
| final AccountTypeManager accountTypes = getAccountTypes(accountType); |
| final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Build "before" with two phone numbers |
| final ContentValues first = new ContentValues(); |
| first.put(Data._ID, TEST_ID); |
| first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| first.put(kindPhone.typeColumn, typeHome.rawValue); |
| first.put(Phone.NUMBER, TEST_PHONE); |
| |
| final ContentValues second = new ContentValues(); |
| second.put(Data._ID, TEST_ID); |
| second.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| second.put(kindPhone.typeColumn, typeHome.rawValue); |
| second.put(Phone.NUMBER, TEST_PHONE); |
| |
| final RawContactDelta state = getRawContact(TEST_ID, first, second); |
| final RawContactDeltaList set = new RawContactDeltaList(); |
| set.add(state); |
| |
| // Build diff, expecting no changes |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| |
| // Now update row by changing number to empty string, expecting single update |
| final ValuesDelta child = state.getEntry(TEST_ID); |
| child.put(Phone.NUMBER, ""); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 3, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(1); |
| assertEquals("Incorrect type", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(2); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| |
| // Now run trim, which should turn that update into delete |
| RawContactModifier.trimEmpty(set, accountTypes); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 3, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(1); |
| assertEquals("Incorrect type", TYPE_DELETE, oper.getType()); |
| assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(2); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| } |
| |
| public void testTrimUpdateUpdate() { |
| final AccountType accountType = getAccountType(); |
| final AccountTypeManager accountTypes = getAccountTypes(accountType); |
| final DataKind kindPhone = accountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| final EditType typeHome = RawContactModifier.getType(kindPhone, Phone.TYPE_HOME); |
| |
| // Build "before" with two phone numbers |
| final ContentValues first = new ContentValues(); |
| first.put(Data._ID, TEST_ID); |
| first.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| first.put(kindPhone.typeColumn, typeHome.rawValue); |
| first.put(Phone.NUMBER, TEST_PHONE); |
| |
| final RawContactDelta state = getRawContact(TEST_ID, first); |
| final RawContactDeltaList set = new RawContactDeltaList(); |
| set.add(state); |
| |
| // Build diff, expecting no changes |
| final ArrayList<ContentProviderOperation> diff = Lists.newArrayList(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 0, diff.size()); |
| |
| // Now update row by changing number to empty string, expecting single update |
| final ValuesDelta child = state.getEntry(TEST_ID); |
| child.put(Phone.NUMBER, ""); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 3, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(1); |
| assertEquals("Incorrect type", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", Data.CONTENT_URI, oper.getUri()); |
| } |
| { |
| final ContentProviderOperation oper = diff.get(2); |
| assertEquals("Expected aggregation mode change", TYPE_UPDATE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| |
| // Now run trim, which should turn into deleting the whole contact |
| RawContactModifier.trimEmpty(set, accountTypes); |
| diff.clear(); |
| state.buildDiff(diff); |
| assertEquals("Unexpected operations", 1, diff.size()); |
| { |
| final ContentProviderOperation oper = diff.get(0); |
| assertEquals("Incorrect type", TYPE_DELETE, oper.getType()); |
| assertEquals("Incorrect target", RawContacts.CONTENT_URI, oper.getUri()); |
| } |
| } |
| |
| public void testParseExtrasExistingName() { |
| final AccountType accountType = getAccountType(); |
| |
| // Build "before" name |
| final ContentValues first = new ContentValues(); |
| first.put(Data._ID, TEST_ID); |
| first.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); |
| first.put(StructuredName.GIVEN_NAME, TEST_NAME); |
| |
| // Parse extras, making sure we keep single name |
| final RawContactDelta state = getRawContact(TEST_ID, first); |
| final Bundle extras = new Bundle(); |
| extras.putString(Insert.NAME, TEST_NAME2); |
| RawContactModifier.parseExtras(mContext, accountType, state, extras); |
| |
| final int nameCount = state.getMimeEntriesCount(StructuredName.CONTENT_ITEM_TYPE, true); |
| assertEquals("Unexpected names", 1, nameCount); |
| } |
| |
| public void testParseExtrasIgnoreLimit() { |
| final AccountType accountType = getAccountType(); |
| |
| // Build "before" IM |
| final ContentValues first = new ContentValues(); |
| first.put(Data._ID, TEST_ID); |
| first.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); |
| first.put(Im.DATA, TEST_IM); |
| |
| final RawContactDelta state = getRawContact(TEST_ID, first); |
| final int beforeCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size(); |
| |
| // We should ignore data that doesn't fit account type rules, since account type |
| // only allows single Im |
| final Bundle extras = new Bundle(); |
| extras.putInt(Insert.IM_PROTOCOL, Im.PROTOCOL_GOOGLE_TALK); |
| extras.putString(Insert.IM_HANDLE, TEST_IM); |
| RawContactModifier.parseExtras(mContext, accountType, state, extras); |
| |
| final int afterCount = state.getMimeEntries(Im.CONTENT_ITEM_TYPE).size(); |
| assertEquals("Broke account type rules", beforeCount, afterCount); |
| } |
| |
| public void testParseExtrasIgnoreUnhandled() { |
| final AccountType accountType = getAccountType(); |
| final RawContactDelta state = getRawContact(TEST_ID); |
| |
| // We should silently ignore types unsupported by account type |
| final Bundle extras = new Bundle(); |
| extras.putString(Insert.POSTAL, TEST_POSTAL); |
| RawContactModifier.parseExtras(mContext, accountType, state, extras); |
| |
| assertNull("Broke accoun type rules", |
| state.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE)); |
| } |
| |
| public void testParseExtrasJobTitle() { |
| final AccountType accountType = getAccountType(); |
| final RawContactDelta state = getRawContact(TEST_ID); |
| |
| // Make sure that we create partial Organizations |
| final Bundle extras = new Bundle(); |
| extras.putString(Insert.JOB_TITLE, TEST_NAME); |
| RawContactModifier.parseExtras(mContext, accountType, state, extras); |
| |
| final int count = state.getMimeEntries(Organization.CONTENT_ITEM_TYPE).size(); |
| assertEquals("Expected to create organization", 1, count); |
| } |
| |
| public void testMigrateWithDisplayNameFromGoogleToExchange1() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE); |
| |
| ContactsMockContext context = new ContactsMockContext(getContext()); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); |
| mockNameValues.put(StructuredName.PREFIX, "prefix"); |
| mockNameValues.put(StructuredName.GIVEN_NAME, "given"); |
| mockNameValues.put(StructuredName.MIDDLE_NAME, "middle"); |
| mockNameValues.put(StructuredName.FAMILY_NAME, "family"); |
| mockNameValues.put(StructuredName.SUFFIX, "suffix"); |
| mockNameValues.put(StructuredName.PHONETIC_FAMILY_NAME, "PHONETIC_FAMILY"); |
| mockNameValues.put(StructuredName.PHONETIC_MIDDLE_NAME, "PHONETIC_MIDDLE"); |
| mockNameValues.put(StructuredName.PHONETIC_GIVEN_NAME, "PHONETIC_GIVEN"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateStructuredName(context, oldState, newState, kind); |
| List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE); |
| assertEquals(1, list.size()); |
| |
| ContentValues output = list.get(0).getAfter(); |
| assertEquals("prefix", output.getAsString(StructuredName.PREFIX)); |
| assertEquals("given", output.getAsString(StructuredName.GIVEN_NAME)); |
| assertEquals("middle", output.getAsString(StructuredName.MIDDLE_NAME)); |
| assertEquals("family", output.getAsString(StructuredName.FAMILY_NAME)); |
| assertEquals("suffix", output.getAsString(StructuredName.SUFFIX)); |
| // Phonetic middle name isn't supported by Exchange. |
| assertEquals("PHONETIC_FAMILY", output.getAsString(StructuredName.PHONETIC_FAMILY_NAME)); |
| assertEquals("PHONETIC_GIVEN", output.getAsString(StructuredName.PHONETIC_GIVEN_NAME)); |
| } |
| |
| public void testMigrateWithDisplayNameFromGoogleToExchange2() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE); |
| |
| ContactsMockContext context = new ContactsMockContext(getContext()); |
| MockContentProvider provider = context.getContactsProvider(); |
| |
| String inputDisplayName = "prefix given middle family suffix"; |
| // The method will ask the provider to split/join StructuredName. |
| Uri uriForBuildDisplayName = |
| ContactsContract.AUTHORITY_URI |
| .buildUpon() |
| .appendPath("complete_name") |
| .appendQueryParameter(StructuredName.DISPLAY_NAME, inputDisplayName) |
| .build(); |
| provider.expectQuery(uriForBuildDisplayName) |
| .returnRow("prefix", "given", "middle", "family", "suffix") |
| .withProjection(StructuredName.PREFIX, StructuredName.GIVEN_NAME, |
| StructuredName.MIDDLE_NAME, StructuredName.FAMILY_NAME, |
| StructuredName.SUFFIX); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); |
| mockNameValues.put(StructuredName.DISPLAY_NAME, inputDisplayName); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateStructuredName(context, oldState, newState, kind); |
| List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE); |
| assertEquals(1, list.size()); |
| |
| ContentValues outputValues = list.get(0).getAfter(); |
| assertEquals("prefix", outputValues.getAsString(StructuredName.PREFIX)); |
| assertEquals("given", outputValues.getAsString(StructuredName.GIVEN_NAME)); |
| assertEquals("middle", outputValues.getAsString(StructuredName.MIDDLE_NAME)); |
| assertEquals("family", outputValues.getAsString(StructuredName.FAMILY_NAME)); |
| assertEquals("suffix", outputValues.getAsString(StructuredName.SUFFIX)); |
| } |
| |
| public void testMigrateWithStructuredNameFromExchangeToGoogle() { |
| AccountType oldAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| AccountType newAccountType = new GoogleAccountType(getContext(), ""); |
| DataKind kind = newAccountType.getKindForMimetype(StructuredName.CONTENT_ITEM_TYPE); |
| |
| ContactsMockContext context = new ContactsMockContext(getContext()); |
| MockContentProvider provider = context.getContactsProvider(); |
| |
| // The method will ask the provider to split/join StructuredName. |
| Uri uriForBuildDisplayName = |
| ContactsContract.AUTHORITY_URI |
| .buildUpon() |
| .appendPath("complete_name") |
| .appendQueryParameter(StructuredName.PREFIX, "prefix") |
| .appendQueryParameter(StructuredName.GIVEN_NAME, "given") |
| .appendQueryParameter(StructuredName.MIDDLE_NAME, "middle") |
| .appendQueryParameter(StructuredName.FAMILY_NAME, "family") |
| .appendQueryParameter(StructuredName.SUFFIX, "suffix") |
| .build(); |
| provider.expectQuery(uriForBuildDisplayName) |
| .returnRow("prefix given middle family suffix") |
| .withProjection(StructuredName.DISPLAY_NAME); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE); |
| mockNameValues.put(StructuredName.PREFIX, "prefix"); |
| mockNameValues.put(StructuredName.GIVEN_NAME, "given"); |
| mockNameValues.put(StructuredName.MIDDLE_NAME, "middle"); |
| mockNameValues.put(StructuredName.FAMILY_NAME, "family"); |
| mockNameValues.put(StructuredName.SUFFIX, "suffix"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateStructuredName(context, oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(StructuredName.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(1, list.size()); |
| ContentValues outputValues = list.get(0).getAfter(); |
| assertEquals("prefix given middle family suffix", |
| outputValues.getAsString(StructuredName.DISPLAY_NAME)); |
| } |
| |
| public void testMigratePostalFromGoogleToExchange() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); |
| mockNameValues.put(StructuredPostal.FORMATTED_ADDRESS, "formatted_address"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migratePostal(oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(1, list.size()); |
| ContentValues outputValues = list.get(0).getAfter(); |
| // FORMATTED_ADDRESS isn't supported by Exchange. |
| assertNull(outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS)); |
| assertEquals("formatted_address", outputValues.getAsString(StructuredPostal.STREET)); |
| } |
| |
| public void testMigratePostalFromExchangeToGoogle() { |
| AccountType oldAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| AccountType newAccountType = new GoogleAccountType(getContext(), ""); |
| DataKind kind = newAccountType.getKindForMimetype(StructuredPostal.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, StructuredPostal.CONTENT_ITEM_TYPE); |
| mockNameValues.put(StructuredPostal.COUNTRY, "country"); |
| mockNameValues.put(StructuredPostal.POSTCODE, "postcode"); |
| mockNameValues.put(StructuredPostal.REGION, "region"); |
| mockNameValues.put(StructuredPostal.CITY, "city"); |
| mockNameValues.put(StructuredPostal.STREET, "street"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migratePostal(oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(StructuredPostal.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(1, list.size()); |
| ContentValues outputValues = list.get(0).getAfter(); |
| |
| // Check FORMATTED_ADDRESS contains all info. |
| String formattedAddress = outputValues.getAsString(StructuredPostal.FORMATTED_ADDRESS); |
| assertNotNull(formattedAddress); |
| assertTrue(formattedAddress.contains("country")); |
| assertTrue(formattedAddress.contains("postcode")); |
| assertTrue(formattedAddress.contains("region")); |
| assertTrue(formattedAddress.contains("postcode")); |
| assertTrue(formattedAddress.contains("city")); |
| assertTrue(formattedAddress.contains("street")); |
| } |
| |
| public void testMigrateEventFromGoogleToExchange1() { |
| testMigrateEventCommon(new GoogleAccountType(getContext(), ""), |
| new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE)); |
| } |
| |
| public void testMigrateEventFromExchangeToGoogle() { |
| testMigrateEventCommon(new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE), |
| new GoogleAccountType(getContext(), "")); |
| } |
| |
| private void testMigrateEventCommon(AccountType oldAccountType, AccountType newAccountType) { |
| DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Event.START_DATE, "1972-02-08"); |
| mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateEvent(oldState, newState, kind, 1990); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(1, list.size()); // Anniversary should be dropped. |
| ContentValues outputValues = list.get(0).getAfter(); |
| |
| assertEquals("1972-02-08", outputValues.getAsString(Event.START_DATE)); |
| assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue()); |
| } |
| |
| public void testMigrateEventFromGoogleToExchange2() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(Event.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE); |
| // No year format is not supported by Exchange. |
| mockNameValues.put(Event.START_DATE, "--06-01"); |
| mockNameValues.put(Event.TYPE, Event.TYPE_BIRTHDAY); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Event.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Event.START_DATE, "1980-08-02"); |
| // Anniversary is not supported by Exchange |
| mockNameValues.put(Event.TYPE, Event.TYPE_ANNIVERSARY); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateEvent(oldState, newState, kind, 1990); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(Event.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(1, list.size()); // Anniversary should be dropped. |
| ContentValues outputValues = list.get(0).getAfter(); |
| |
| // Default year should be used. |
| assertEquals("1990-06-01", outputValues.getAsString(Event.START_DATE)); |
| assertEquals(Event.TYPE_BIRTHDAY, outputValues.getAsInteger(Event.TYPE).intValue()); |
| } |
| |
| public void testMigrateEmailFromGoogleToExchange() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(Email.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Email.TYPE, Email.TYPE_CUSTOM); |
| mockNameValues.put(Email.LABEL, "custom_type"); |
| mockNameValues.put(Email.ADDRESS, "address1"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Email.TYPE, Email.TYPE_HOME); |
| mockNameValues.put(Email.ADDRESS, "address2"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Email.TYPE, Email.TYPE_WORK); |
| mockNameValues.put(Email.ADDRESS, "address3"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| // Exchange can have up to 3 email entries. This 4th entry should be dropped. |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Email.TYPE, Email.TYPE_OTHER); |
| mockNameValues.put(Email.ADDRESS, "address4"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(Email.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(3, list.size()); |
| |
| ContentValues outputValues = list.get(0).getAfter(); |
| assertEquals(Email.TYPE_CUSTOM, outputValues.getAsInteger(Email.TYPE).intValue()); |
| assertEquals("custom_type", outputValues.getAsString(Email.LABEL)); |
| assertEquals("address1", outputValues.getAsString(Email.ADDRESS)); |
| |
| outputValues = list.get(1).getAfter(); |
| assertEquals(Email.TYPE_HOME, outputValues.getAsInteger(Email.TYPE).intValue()); |
| assertEquals("address2", outputValues.getAsString(Email.ADDRESS)); |
| |
| outputValues = list.get(2).getAfter(); |
| assertEquals(Email.TYPE_WORK, outputValues.getAsInteger(Email.TYPE).intValue()); |
| assertEquals("address3", outputValues.getAsString(Email.ADDRESS)); |
| } |
| |
| public void testMigrateImFromGoogleToExchange() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(Im.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); |
| // Exchange doesn't support TYPE_HOME |
| mockNameValues.put(Im.TYPE, Im.TYPE_HOME); |
| mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_JABBER); |
| mockNameValues.put(Im.DATA, "im1"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); |
| // Exchange doesn't support TYPE_WORK |
| mockNameValues.put(Im.TYPE, Im.TYPE_WORK); |
| mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_YAHOO); |
| mockNameValues.put(Im.DATA, "im2"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Im.TYPE, Im.TYPE_OTHER); |
| mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_CUSTOM); |
| mockNameValues.put(Im.CUSTOM_PROTOCOL, "custom_protocol"); |
| mockNameValues.put(Im.DATA, "im3"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| // Exchange can have up to 3 IM entries. This 4th entry should be dropped. |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Im.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Im.TYPE, Im.TYPE_OTHER); |
| mockNameValues.put(Im.PROTOCOL, Im.PROTOCOL_GOOGLE_TALK); |
| mockNameValues.put(Im.DATA, "im4"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(Im.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(3, list.size()); |
| |
| assertNotNull(kind.defaultValues.getAsInteger(Im.TYPE)); |
| |
| int defaultType = kind.defaultValues.getAsInteger(Im.TYPE); |
| |
| ContentValues outputValues = list.get(0).getAfter(); |
| // HOME should become default type. |
| assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue()); |
| assertEquals(Im.PROTOCOL_JABBER, outputValues.getAsInteger(Im.PROTOCOL).intValue()); |
| assertEquals("im1", outputValues.getAsString(Im.DATA)); |
| |
| outputValues = list.get(1).getAfter(); |
| assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue()); |
| assertEquals(Im.PROTOCOL_YAHOO, outputValues.getAsInteger(Im.PROTOCOL).intValue()); |
| assertEquals("im2", outputValues.getAsString(Im.DATA)); |
| |
| outputValues = list.get(2).getAfter(); |
| assertEquals(defaultType, outputValues.getAsInteger(Im.TYPE).intValue()); |
| assertEquals(Im.PROTOCOL_CUSTOM, outputValues.getAsInteger(Im.PROTOCOL).intValue()); |
| assertEquals("custom_protocol", outputValues.getAsString(Im.CUSTOM_PROTOCOL)); |
| assertEquals("im3", outputValues.getAsString(Im.DATA)); |
| } |
| |
| public void testMigratePhoneFromGoogleToExchange() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(Phone.CONTENT_ITEM_TYPE); |
| |
| // Create 5 numbers. |
| // - "1" -- HOME |
| // - "2" -- WORK |
| // - "3" -- CUSTOM |
| // - "4" -- WORK |
| // - "5" -- WORK_MOBILE |
| // Then we convert it to Exchange account type. |
| // - "1" -- HOME |
| // - "2" -- WORK |
| // - "3" -- Because CUSTOM is not supported, it'll be changed to the default, MOBILE |
| // - "4" -- WORK |
| // - "5" -- WORK_MOBILE not suppoted again, so will be MOBILE. |
| // But then, Exchange doesn't support multiple MOBILE numbers, so "5" will be removed. |
| // i.e. the result will be: |
| // - "1" -- HOME |
| // - "2" -- WORK |
| // - "3" -- MOBILE |
| // - "4" -- WORK |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Phone.TYPE, Phone.TYPE_HOME); |
| mockNameValues.put(Phone.NUMBER, "1"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK); |
| mockNameValues.put(Phone.NUMBER, "2"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| // Exchange doesn't support this type. Default to MOBILE |
| mockNameValues.put(Phone.TYPE, Phone.TYPE_CUSTOM); |
| mockNameValues.put(Phone.LABEL, "custom_type"); |
| mockNameValues.put(Phone.NUMBER, "3"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK); |
| mockNameValues.put(Phone.NUMBER, "4"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| mockNameValues = new ContentValues(); |
| |
| mockNameValues.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Phone.TYPE, Phone.TYPE_WORK_MOBILE); |
| mockNameValues.put(Phone.NUMBER, "5"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateGenericWithTypeColumn(oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(Phone.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(4, list.size()); |
| |
| int defaultType = Phone.TYPE_MOBILE; |
| |
| ContentValues outputValues = list.get(0).getAfter(); |
| assertEquals(Phone.TYPE_HOME, outputValues.getAsInteger(Phone.TYPE).intValue()); |
| assertEquals("1", outputValues.getAsString(Phone.NUMBER)); |
| outputValues = list.get(1).getAfter(); |
| assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue()); |
| assertEquals("2", outputValues.getAsString(Phone.NUMBER)); |
| outputValues = list.get(2).getAfter(); |
| assertEquals(defaultType, outputValues.getAsInteger(Phone.TYPE).intValue()); |
| assertNull(outputValues.getAsInteger(Phone.LABEL)); |
| assertEquals("3", outputValues.getAsString(Phone.NUMBER)); |
| outputValues = list.get(3).getAfter(); |
| assertEquals(Phone.TYPE_WORK, outputValues.getAsInteger(Phone.TYPE).intValue()); |
| assertEquals("4", outputValues.getAsString(Phone.NUMBER)); |
| } |
| |
| public void testMigrateOrganizationFromGoogleToExchange() { |
| AccountType oldAccountType = new GoogleAccountType(getContext(), ""); |
| AccountType newAccountType = new ExchangeAccountType(getContext(), "", EXCHANGE_ACCT_TYPE); |
| DataKind kind = newAccountType.getKindForMimetype(Organization.CONTENT_ITEM_TYPE); |
| |
| RawContactDelta oldState = new RawContactDelta(); |
| ContentValues mockNameValues = new ContentValues(); |
| mockNameValues.put(Data.MIMETYPE, Organization.CONTENT_ITEM_TYPE); |
| mockNameValues.put(Organization.COMPANY, "company1"); |
| mockNameValues.put(Organization.DEPARTMENT, "department1"); |
| oldState.addEntry(ValuesDelta.fromAfter(mockNameValues)); |
| |
| RawContactDelta newState = new RawContactDelta(); |
| RawContactModifier.migrateGenericWithoutTypeColumn(oldState, newState, kind); |
| |
| List<ValuesDelta> list = newState.getMimeEntries(Organization.CONTENT_ITEM_TYPE); |
| assertNotNull(list); |
| assertEquals(1, list.size()); |
| |
| ContentValues outputValues = list.get(0).getAfter(); |
| assertEquals("company1", outputValues.getAsString(Organization.COMPANY)); |
| assertEquals("department1", outputValues.getAsString(Organization.DEPARTMENT)); |
| } |
| } |