/* * CDDL HEADER START * * The contents of this file are subject to the terms of the Common Development * and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at * src/com/vodafone360/people/VODAFONE.LICENSE.txt or * http://github.com/360/360-Engine-for-Android * See the License for the specific language governing permissions and * limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each file and * include the License file at src/com/vodafone360/people/VODAFONE.LICENSE.txt. * If applicable, add the following below this CDDL HEADER, with the fields * enclosed by brackets "[]" replaced with your own identifying information: * Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END * * Copyright 2010 Vodafone Sales & Services Ltd. All rights reserved. * Use is subject to license terms. */ package com.vodafone360.people.tests.engine.contactsync; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import android.app.Instrumentation; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.Suppress; import android.util.Log; import com.vodafone360.people.MainApplication; import com.vodafone360.people.database.DatabaseHelper; import com.vodafone360.people.database.tables.ContactChangeLogTable; import com.vodafone360.people.database.tables.ContactDetailsTable; import com.vodafone360.people.database.tables.ContactSummaryTable; import com.vodafone360.people.datatypes.BaseDataType; import com.vodafone360.people.datatypes.Contact; import com.vodafone360.people.datatypes.ContactChanges; import com.vodafone360.people.datatypes.ContactDetail; import com.vodafone360.people.datatypes.ContactDetailDeletion; import com.vodafone360.people.datatypes.ContactListResponse; import com.vodafone360.people.datatypes.ContactSummary; import com.vodafone360.people.datatypes.GroupItem; import com.vodafone360.people.datatypes.ItemList; import com.vodafone360.people.datatypes.ServerError; import com.vodafone360.people.datatypes.StatusMsg; import com.vodafone360.people.engine.EngineManager.EngineId; import com.vodafone360.people.engine.contactsync.IContactSyncCallback; import com.vodafone360.people.engine.contactsync.UploadServerContacts; import com.vodafone360.people.service.ServiceStatus; import com.vodafone360.people.service.agent.NetworkAgent; import com.vodafone360.people.service.io.ResponseQueue; import com.vodafone360.people.service.io.ResponseQueue.DecodedResponse; import com.vodafone360.people.tests.TestModule; import com.vodafone360.people.tests.engine.EngineTestFramework; import com.vodafone360.people.tests.engine.IEngineTestFrameworkObserver; public class UploadServerContactsTest extends InstrumentationTestCase implements IEngineTestFrameworkObserver { private static final String LOG_TAG = "UploadServerContactsTest"; private static final long MAX_PROCESSOR_TIME = 3000000; private static final long MAX_WAIT_FOR_REQ_ID = 5000; private static final int NO_OF_CONTACTS_TO_ADD = 55; private static final String NEW_DETAIL_VALUE = "0123456789"; private static final ContactDetail.DetailKeys NEW_DETAIL_KEY = ContactDetail.DetailKeys.VCARD_PHONE; private static final ContactDetail.DetailKeyTypes NEW_DETAIL_TYPE = ContactDetail.DetailKeyTypes.CELL; private static final String MOD_DETAIL_VALUE = ";Test;One"; private static final ContactDetail.DetailKeys MOD_DETAIL_KEY = ContactDetail.DetailKeys.VCARD_NAME; private static final ContactDetail.DetailKeyTypes MOD_DETAIL_TYPE = null; private static final long TEST_GROUP_1 = 860909; private static final long TEST_GROUP_2 = 860910; enum State { IDLE, ADD_CONTACT_LIST, MODIFY_CONTACT_LIST, DELETE_CONTACT_LIST, DELETE_CONTACT_DETAIL_LIST, ADD_NEW_GROUP_LIST, DELETE_GROUP_LIST } EngineTestFramework mEngineTester = null; MainApplication mApplication = null; DummyContactSyncEngine mEng = null; class UploadServerContactProcessorTest extends UploadServerContacts { public UploadServerContactProcessorTest(IContactSyncCallback callback, DatabaseHelper db) { super(callback, db); } public void testFetchContactChangeList(List<Contact> contactChangeList) { contactChangeList.clear(); contactChangeList.addAll(getContactChangeList()); } public void testFetchAddGroupLists(List<Long> contactIdList, List<GroupItem> groupList) { contactIdList.clear(); groupList.clear(); contactIdList.addAll(getContactIdList()); groupList.addAll(getGroupList()); } public void testFetchContactDeleteList(List<Long> contactIdList) { contactIdList.clear(); contactIdList.addAll(getContactIdList()); } public void testFetchContactDetailDeleteList(Contact deleteDetailContact) { android.os.Parcel _data = android.os.Parcel.obtain(); getDeleteDetailContact().writeToParcel(_data, 0); _data.setDataPosition(0); deleteDetailContact.readFromParcel(_data); } public Long testFetchDeleteGroupList(List<Long> contactIdList) { contactIdList.clear(); contactIdList.addAll(getContactIdList()); return getActiveGroupId(); } public int testGetPageSize() { return MAX_UP_PAGE_SIZE; } public void verifyNewContactsState() { assertEquals(InternalState.PROCESSING_NEW_CONTACTS, getInternalState()); } public void verifyModifyDetailsState() { assertEquals(InternalState.PROCESSING_MODIFIED_DETAILS, getInternalState()); } public void verifyDeleteContactsState() { assertEquals(InternalState.PROCESSING_DELETED_CONTACTS, getInternalState()); } public void verifyDeleteDetailsState() { assertEquals(InternalState.PROCESSING_DELETED_DETAILS, getInternalState()); } public void verifyGroupAddsState() { assertEquals(InternalState.PROCESSING_GROUP_ADDITIONS, getInternalState()); } public void verifyGroupDelsState() { assertEquals(InternalState.PROCESSING_GROUP_DELETIONS, getInternalState()); } }; UploadServerContactProcessorTest mProcessor; DatabaseHelper mDb = null; State mState = State.IDLE; Contact mReplyContact = null; int mInitialCount; int mInitialContactGroupCount; int mItemCount; boolean mBulkContactTest; TestModule mTestModule = new TestModule(); int mTestStep; @Override protected void setUp() throws Exception { super.setUp(); mApplication = (MainApplication)Instrumentation.newApplication(MainApplication.class, getInstrumentation().getTargetContext()); mApplication.onCreate(); mDb = mApplication.getDatabase(); mDb.removeUserData(); mEngineTester = new EngineTestFramework(this); mEng = new DummyContactSyncEngine(mEngineTester); mProcessor = new UploadServerContactProcessorTest(mEng, mApplication.getDatabase()); mEng.setProcessor(mProcessor); mEngineTester.setEngine(mEng); mState = State.IDLE; NetworkAgent.setAgentState(NetworkAgent.AgentState.CONNECTED); mBulkContactTest = false; } @Override protected void tearDown() throws Exception { // stop our dummy thread? mEngineTester.stopEventThread(); mEngineTester = null; mEng = null; SQLiteDatabase db = mDb.getReadableDatabase(); if (db.inTransaction()) { db.endTransaction(); } db.close(); super.tearDown(); } private void startSubTest(String function, String description) { Log.i(LOG_TAG, function + " - step " + mTestStep + ": " + description); mTestStep++; } private void runProcessor(int count, State state) { mInitialCount = count; nextState(state); mEng.mProcessorCompleteFlag = false; mProcessor.start(); ServiceStatus status = mEng.waitForProcessorComplete(MAX_PROCESSOR_TIME); assertEquals(ServiceStatus.SUCCESS, status); } private void nextState(State state) { mItemCount = mInitialCount; if (mItemCount == 0) { mState = State.IDLE; } else { mState = state; } } @Override public void reportBackToEngine(int reqId, EngineId engine) { Log.d(LOG_TAG, "reportBackToEngine"); ResponseQueue respQueue = ResponseQueue.getInstance(); List<BaseDataType> data = new ArrayList<BaseDataType>(); try { assertEquals(mEng.engineId(), engine); synchronized (mEng.mWaitForReqIdLock) { if (mEng.mActiveReqId == null || mEng.mActiveReqId.intValue() != reqId) { try { mEng.mWaitForReqIdLock.wait(MAX_WAIT_FOR_REQ_ID); } catch (InterruptedException e) { } assertEquals(Integer.valueOf(reqId), mEng.mActiveReqId); } } switch (mState) { case ADD_CONTACT_LIST: reportBackAddContactSuccess(reqId, data); break; case MODIFY_CONTACT_LIST: reportModifyContactSuccess(reqId, data); break; case DELETE_CONTACT_LIST: reportDeleteContactSuccess(reqId, data); break; case DELETE_CONTACT_DETAIL_LIST: reportDeleteContactDetailSuccess(reqId, data); break; case ADD_NEW_GROUP_LIST: reportBackAddGroupSuccess(reqId, data); break; case DELETE_GROUP_LIST: reportDeleteGroupListSuccess(reqId, data); break; default: fail("Unexpected request from processor"); } } catch (Throwable err) { ServerError serverError = new ServerError(ServerError.ErrorType.INTERNALERROR); serverError.errorDescription = err + "\n"; for (int i = 0; i < err.getStackTrace().length; i++) { StackTraceElement v = err.getStackTrace()[i]; serverError.errorDescription += "\t" + v + "\n"; } Log.e(LOG_TAG, "Exception:\n" + serverError.errorDescription); data.clear(); data.add(serverError); } respQueue.addToResponseQueue(new DecodedResponse(reqId, data, engine, DecodedResponse.ResponseType.SERVER_ERROR.ordinal())); mEng.onCommsInMessage(); Log.d(LOG_TAG, "reportBackToEngine - message added to response queue"); } private void reportBackAddContactSuccess(int reqId, List<BaseDataType> data) { Log.d(LOG_TAG, "reportBackAddContactSuccess"); mProcessor.verifyNewContactsState(); List<Contact> contactChangeList = new ArrayList<Contact>(); mProcessor.testFetchContactChangeList(contactChangeList); assertEquals(Math.min(mItemCount, mProcessor.testGetPageSize()), contactChangeList.size()); ContactChanges contactChanges = new ContactChanges(); contactChanges.mServerRevisionAfter = 1; contactChanges.mServerRevisionBefore = 0; data.add(contactChanges); for (int i = 0; i < contactChangeList.size(); i++) { Contact actualContact = contactChangeList.get(i); Contact expectedContact = new Contact(); ServiceStatus status = mDb.fetchContact(actualContact.localContactID, expectedContact); assertEquals(ServiceStatus.SUCCESS, status); assertEquals(expectedContact.details.size(), actualContact.details.size()); assertEquals(null, actualContact.aboutMe); assertEquals(null, actualContact.profilePath); assertEquals(null, actualContact.contactID); assertEquals(null, actualContact.deleted); assertEquals(null, actualContact.friendOfMine); assertEquals(null, actualContact.gender); assertEquals(null, actualContact.groupList); assertEquals(null, actualContact.sources); assertEquals(expectedContact.synctophone, actualContact.synctophone); assertEquals(null, actualContact.updated); assertEquals(null, actualContact.userID); final ListIterator<ContactDetail> itActDetails = actualContact.details.listIterator(); for (ContactDetail expDetail : expectedContact.details) { ContactDetail actDetail = itActDetails.next(); assertTrue(DatabaseHelper.doDetailsMatch(expDetail, actDetail)); assertFalse(DatabaseHelper.hasDetailChanged(expDetail, actDetail)); } generateReplyContact(expectedContact); contactChanges.mContacts.add(mReplyContact); } mItemCount -= contactChangeList.size(); assertTrue(mItemCount >= 0); if (mItemCount == 0) { mInitialCount = mInitialContactGroupCount; nextState(State.ADD_NEW_GROUP_LIST); } } private void reportBackAddGroupSuccess(int reqId, List<BaseDataType> data) { Log.d(LOG_TAG, "reportBackAddGroupSuccess"); mProcessor.verifyGroupAddsState(); final List<Long> contactIdList = new ArrayList<Long>(); final List<GroupItem> groupList = new ArrayList<GroupItem>(); mProcessor.testFetchAddGroupLists(contactIdList, groupList); assertEquals(1, groupList.size()); Long activeGroupId = groupList.get(0).mId; assertTrue(activeGroupId != null); ItemList itemList = new ItemList(ItemList.Type.contact_group_relations); data.add(itemList); for (Long contactServerId : contactIdList) { Contact expectedContact = new Contact(); ServiceStatus status = mDb.fetchContactByServerId(contactServerId, expectedContact); assertEquals(ServiceStatus.SUCCESS, status); boolean found = false; for (Long groupId : expectedContact.groupList) { if (groupId.equals(activeGroupId)) { found = true; break; } } assertTrue("Contact " + contactServerId + " has been added to group " + activeGroupId + " which is not in the database", found); mItemCount--; } Log.i(LOG_TAG, "Groups/contacts remaining = " + mItemCount); assertTrue(mItemCount >= 0); if (mItemCount == 0) { nextState(State.IDLE); } } private void reportModifyContactSuccess(int reqId, List<BaseDataType> data) { Log.d(LOG_TAG, "reportModifyContactSuccess"); mProcessor.verifyModifyDetailsState(); List<Contact> contactChangeList = new ArrayList<Contact>(); mProcessor.testFetchContactChangeList(contactChangeList); assertEquals(Math.min(mItemCount, mProcessor.testGetPageSize()), contactChangeList.size()); ContactChanges contactChanges = new ContactChanges(); contactChanges.mServerRevisionAfter = 1; contactChanges.mServerRevisionBefore = 0; data.add(contactChanges); for (int i = 0; i < contactChangeList.size(); i++) { Contact actualContact = contactChangeList.get(i); assertTrue(actualContact.contactID != null); assertEquals(null, actualContact.aboutMe); assertEquals(null, actualContact.profilePath); assertEquals(null, actualContact.deleted); assertEquals(null, actualContact.friendOfMine); assertEquals(null, actualContact.gender); assertEquals(null, actualContact.groupList); assertEquals(null, actualContact.sources); assertEquals(null, actualContact.synctophone); assertEquals(null, actualContact.updated); assertEquals(null, actualContact.userID); assertEquals(2, actualContact.details.size()); ContactDetail modDetail = actualContact.details.get(0); // Modified // detail // always // first ContactDetail newDetail = actualContact.details.get(1); assertEquals(NEW_DETAIL_VALUE, newDetail.value); assertEquals(NEW_DETAIL_KEY, newDetail.key); assertEquals(NEW_DETAIL_TYPE, newDetail.keyType); assertEquals(MOD_DETAIL_VALUE, modDetail.value); assertEquals(MOD_DETAIL_KEY, modDetail.key); assertEquals(MOD_DETAIL_TYPE, modDetail.keyType); mReplyContact = new Contact(); mReplyContact.contactID = actualContact.contactID; mReplyContact.userID = generateTestUserID(mReplyContact.contactID); ContactDetail replyDetail1 = new ContactDetail(); ContactDetail replyDetail2 = new ContactDetail(); replyDetail1.key = modDetail.key; replyDetail1.unique_id = modDetail.unique_id; replyDetail2.key = newDetail.key; replyDetail2.unique_id = newDetail.localDetailID + 2; mReplyContact.details.add(replyDetail1); mReplyContact.details.add(replyDetail2); contactChanges.mContacts.add(mReplyContact); } mItemCount -= contactChangeList.size(); assertTrue(mItemCount >= 0); if (mItemCount == 0) { nextState(State.IDLE); } } private void reportDeleteContactSuccess(int reqId, List<BaseDataType> data) { Log.d(LOG_TAG, "reportDeleteContactSuccess"); mProcessor.verifyDeleteContactsState(); List<Long> contactIdList = new ArrayList<Long>(); mProcessor.testFetchContactDeleteList(contactIdList); assertEquals(Math.min(mItemCount, mProcessor.testGetPageSize()), contactIdList.size()); ContactListResponse contactListResponse = new ContactListResponse(); contactListResponse.mServerRevisionAfter = 1; contactListResponse.mServerRevisionBefore = 0; data.add(contactListResponse); contactListResponse.mContactIdList = new ArrayList<Integer>(); for (Long serverID : contactIdList) { assertTrue(serverID != null); contactListResponse.mContactIdList.add(Integer.valueOf(serverID.intValue())); } mItemCount -= contactIdList.size(); assertTrue(mItemCount >= 0); if (mItemCount == 0) { nextState(State.IDLE); } } private void reportDeleteContactDetailSuccess(int reqId, List<BaseDataType> data) { Log.d(LOG_TAG, "reportDeleteContactDetailSuccess"); mProcessor.verifyDeleteDetailsState(); Contact contact = new Contact(); mProcessor.testFetchContactDetailDeleteList(contact); assertEquals(2, contact.details.size()); assertEquals(ContactDetail.DetailKeys.VCARD_NAME, contact.details.get(0).key); assertEquals(ContactDetail.DetailKeys.VCARD_PHONE, contact.details.get(1).key); ContactDetailDeletion contactDetailDeletion = new ContactDetailDeletion(); contactDetailDeletion.mServerVersionAfter = 1; contactDetailDeletion.mServerVersionBefore = 0; data.add(contactDetailDeletion); contactDetailDeletion.mContactId = contact.contactID.intValue(); contactDetailDeletion.mDetails = new ArrayList<ContactDetail>(); for (ContactDetail detail : contact.details) { ContactDetail tempDetail = new ContactDetail(); tempDetail.key = detail.key; tempDetail.unique_id = detail.unique_id; contactDetailDeletion.mDetails.add(tempDetail); } mItemCount--; assertTrue(mItemCount >= 0); if (mItemCount == 0) { nextState(State.IDLE); } } private void reportDeleteGroupListSuccess(int reqId, List<BaseDataType> data) { Log.d(LOG_TAG, "reportDeleteGroupListSuccess"); mProcessor.verifyGroupDelsState(); final List<Long> contactIdList = new ArrayList<Long>(); Long activeGroupId = mProcessor.testFetchDeleteGroupList(contactIdList); if (mItemCount == 1) { assertEquals(Long.valueOf(TEST_GROUP_2), activeGroupId); } else if (mItemCount == 2) { assertEquals(Long.valueOf(TEST_GROUP_1), activeGroupId); } else { fail("Unexpected number of groups in delete group list"); } StatusMsg statusMsg = new StatusMsg(); statusMsg.mStatus = true; data.add(statusMsg); mItemCount--; assertTrue(mItemCount >= 0); if (mItemCount == 0) { nextState(State.IDLE); } } private Long generateTestUserID(Long contactID) { if (contactID == null) { return null; } if ((contactID & 15) == 0) { return null; } return contactID + 5; } private void generateReplyContact(Contact expContact) { mReplyContact = new Contact(); mReplyContact.contactID = expContact.localContactID + 1; if ((expContact.localContactID & 15) != 0) { mReplyContact.userID = expContact.localContactID + 2; } for (ContactDetail detail : expContact.details) { ContactDetail newDetail = new ContactDetail(); generateReplyDetail(newDetail, detail); mReplyContact.details.add(newDetail); } } private void generateReplyDetail(ContactDetail replyDetail, ContactDetail expDetail) { replyDetail.key = expDetail.key; switch (replyDetail.key) { case VCARD_NAME: case VCARD_NICKNAME: case VCARD_DATE: case VCARD_TITLE: case PRESENCE_TEXT: case PHOTO: case LOCATION: break; default: replyDetail.unique_id = expDetail.localDetailID + 3; break; } } @Override public void onEngineException(Exception e) { mEng.onProcessorComplete(ServiceStatus.ERROR_UNKNOWN, "", e); } @SmallTest @Suppress // Breaks tests public void testRunWithNoContactChanges() { final String fnName = "testRunWithNoContactChanges"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor"); mProcessor.start(); ServiceStatus status = mEng.waitForProcessorComplete(MAX_PROCESSOR_TIME); assertEquals(ServiceStatus.SUCCESS, status); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @MediumTest @Suppress // Breaks tests public void testRunWithNewContactChange() { final String fnName = "testRunWithNewContactChange"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database"); Contact contact = mTestModule.createDummyContactData(); ServiceStatus status = mDb.addContact(contact); assertEquals(ServiceStatus.SUCCESS, status); mInitialContactGroupCount = contact.groupList.size(); startSubTest(fnName, "Running processor"); runProcessor(1, State.ADD_CONTACT_LIST); startSubTest(fnName, "Fetching contact after sync"); Contact syncContact = mTestModule.createDummyContactData(); status = mDb.fetchContact(contact.localContactID, syncContact); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Check contact server ID is correct"); assertEquals(syncContact.contactID, mReplyContact.contactID); startSubTest(fnName, "Check detail server IDs are correct"); final ListIterator<ContactDetail> itReplyDetails = mReplyContact.details.listIterator(); for (ContactDetail syncDetail : syncContact.details) { ContactDetail replyDetail = itReplyDetails.next(); assertEquals(replyDetail.key, syncDetail.key); assertEquals(replyDetail.unique_id, syncDetail.unique_id); } noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); assertEquals(State.IDLE, mState); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @MediumTest @Suppress // Breaks tests public void testRunWithDetailChanges() { final String fnName = "testRunWithDetailChanges"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database"); Contact contact = mTestModule.createDummyContactData(); contact.contactID = TestModule.generateRandomLong(); contact.userID = generateTestUserID(contact.contactID); List<Contact> contactList = new ArrayList<Contact>(); contactList.add(contact); ServiceStatus status = mDb.syncAddContactList(contactList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Adding new detail to contact"); ContactDetail newDetail = new ContactDetail(); newDetail.value = NEW_DETAIL_VALUE; newDetail.key = NEW_DETAIL_KEY; newDetail.keyType = NEW_DETAIL_TYPE; newDetail.localContactID = contact.localContactID; status = mDb.addContactDetail(newDetail); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Modifying detail in contact"); ContactDetail modDetail = contact.details.get(0); modDetail.value = MOD_DETAIL_VALUE; modDetail.key = MOD_DETAIL_KEY; modDetail.keyType = MOD_DETAIL_TYPE; status = mDb.modifyContactDetail(modDetail); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(1, State.MODIFY_CONTACT_LIST); startSubTest(fnName, "Fetching detail after sync"); Contact syncContact = new Contact(); status = mDb.fetchContact(contact.localContactID, syncContact); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Check contact server ID is correct"); boolean done = false; for (ContactDetail detail : syncContact.details) { if (detail.localDetailID.equals(newDetail.localDetailID)) { assertEquals(detail.unique_id, Long.valueOf(detail.localDetailID + 2)); done = true; break; } } assertTrue(done); assertEquals(syncContact.contactID, mReplyContact.contactID); assertEquals(syncContact.userID, mReplyContact.userID); assertEquals(State.IDLE, mState); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @MediumTest @Suppress // Breaks tests public void testRunWithContactDeletion() { final String fnName = "testRunWithContactDeletion"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database - no sync"); Contact contact = mTestModule.createDummyContactData(); contact.contactID = TestModule.generateRandomLong(); contact.userID = generateTestUserID(contact.contactID); List<Contact> contactList = new ArrayList<Contact>(); contactList.add(contact); ServiceStatus status = mDb.syncAddContactList(contactList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting contact"); status = mDb.deleteContact(contact.localContactID); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(1, State.DELETE_CONTACT_LIST); assertEquals(State.IDLE, mState); startSubTest(fnName, "Checking change list is empty"); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @MediumTest @Suppress // Breaks tests public void testRunWithContactDetailDeletion() { final String fnName = "testRunWithContactDetailDeletion"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database - no sync"); Contact contact = mTestModule.createDummyContactData(); contact.contactID = TestModule.generateRandomLong(); contact.userID = generateTestUserID(contact.contactID); List<Contact> contactList = new ArrayList<Contact>(); contactList.add(contact); ServiceStatus status = mDb.syncAddContactList(contactList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Adding test contact detail to database - no sync"); ContactDetail detail = new ContactDetail(); detail.value = NEW_DETAIL_VALUE; detail.key = ContactDetail.DetailKeys.VCARD_PHONE; detail.keyType = ContactDetail.DetailKeyTypes.CELL; detail.localContactID = contact.localContactID; List<ContactDetail> contactDetailList = new ArrayList<ContactDetail>(); contactDetailList.add(detail); status = mDb.syncAddContactDetailList(contactDetailList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting contact detail without unique ID"); status = mDb.deleteContactDetail(contact.details.get(0).localDetailID); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting contact detail with unique ID"); status = mDb.deleteContactDetail(detail.localDetailID); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(1, State.DELETE_CONTACT_DETAIL_LIST); assertEquals(State.IDLE, mState); startSubTest(fnName, "Checking change list is empty"); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @MediumTest @Suppress // Breaks tests public void testRunWithGroupRemoval() { final String fnName = "testRunWithGroupRemoval"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database - no sync"); Contact contact = mTestModule.createDummyContactData(); contact.contactID = TestModule.generateRandomLong(); contact.userID = generateTestUserID(contact.contactID); List<Contact> contactList = new ArrayList<Contact>(); contactList.add(contact); contact.groupList.clear(); contact.groupList.add(TEST_GROUP_1); contact.groupList.add(TEST_GROUP_2); ServiceStatus status = mDb.syncAddContactList(contactList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting group 1"); status = mDb.deleteContactFromGroup(contact.localContactID, TEST_GROUP_1); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting group 2"); status = mDb.deleteContactFromGroup(contact.localContactID, TEST_GROUP_2); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(2, State.DELETE_GROUP_LIST); assertEquals(State.IDLE, mState); startSubTest(fnName, "Checking change list is empty"); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @LargeTest @Suppress // Breaks tests public void testRunWithManyContacts() { final String fnName = "testRunWithManyContacts"; mBulkContactTest = true; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding " + NO_OF_CONTACTS_TO_ADD + " test contact to database"); mInitialContactGroupCount = 0; for (int i = 0; i < NO_OF_CONTACTS_TO_ADD; i++) { Contact contact = mTestModule.createDummyContactData(); ServiceStatus status = mDb.addContact(contact); assertEquals(ServiceStatus.SUCCESS, status); mInitialContactGroupCount += contact.groupList.size(); startSubTest(fnName, "Adding new detail to contact"); ContactDetail newDetail = new ContactDetail(); newDetail.value = NEW_DETAIL_VALUE; newDetail.key = NEW_DETAIL_KEY; newDetail.keyType = NEW_DETAIL_TYPE; newDetail.localContactID = contact.localContactID; status = mDb.addContactDetail(newDetail); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Modifying detail in contact"); ContactDetail modDetail = contact.details.get(0); modDetail.value = MOD_DETAIL_VALUE; modDetail.key = MOD_DETAIL_KEY; modDetail.keyType = MOD_DETAIL_TYPE; status = mDb.modifyContactDetail(modDetail); assertEquals(ServiceStatus.SUCCESS, status); } Log.i(LOG_TAG, "Total number of groups = " + mItemCount + " out of " + NO_OF_CONTACTS_TO_ADD + " contacts"); startSubTest(fnName, "Running processor"); runProcessor(NO_OF_CONTACTS_TO_ADD, State.ADD_CONTACT_LIST); startSubTest(fnName, "Fetching contacts after sync"); Cursor cursor = mDb.openContactSummaryCursor(null, null); assertTrue(cursor != null); while (cursor.moveToNext()) { ContactSummary summary = ContactSummaryTable.getQueryData(cursor); Contact testContact = new Contact(); ServiceStatus status = mDb.fetchContact(summary.localContactID, testContact); assertEquals(ServiceStatus.SUCCESS, status); assertEquals(Long.valueOf(summary.localContactID + 1), testContact.contactID); if ((testContact.localContactID & 15) != 0) { assertEquals(Long.valueOf(summary.localContactID + 2), testContact.userID); } else { assertEquals(null, testContact.userID); } for (ContactDetail detail : testContact.details) { ContactDetail replyDetail = new ContactDetail(); generateReplyDetail(replyDetail, detail); assertEquals(replyDetail.unique_id, detail.unique_id); Long syncServerId = TestModule.fetchSyncServerId(detail.localDetailID, mDb .getReadableDatabase()); assertEquals(Long.valueOf(-1), syncServerId); } } cursor.close(); assertEquals(State.IDLE, mState); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); mState = State.IDLE; startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @MediumTest @Suppress // Breaks tests public void testRunWithAddDeleteContactChange() { final String fnName = "testRunWithAddDeleteContactChange"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database"); Contact contact = mTestModule.createDummyContactData(); ServiceStatus status = mDb.addContact(contact); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting contact from database"); status = mDb.deleteContact(contact.localContactID); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(0, State.IDLE); assertEquals(State.IDLE, mState); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @Suppress // Breaks tests public void testRunWithAddDeleteContactDetailChange() { final String fnName = "testRunWithAddDeleteContactDetailChange"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database"); Contact contact = mTestModule.createDummyContactData(); contact.contactID = TestModule.generateRandomLong(); contact.userID = generateTestUserID(contact.contactID); List<Contact> contactList = new ArrayList<Contact>(); contactList.add(contact); ServiceStatus status = mDb.syncAddContactList(contactList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Adding new detail to contact"); ContactDetail newDetail = new ContactDetail(); newDetail.value = NEW_DETAIL_VALUE; newDetail.key = NEW_DETAIL_KEY; newDetail.keyType = NEW_DETAIL_TYPE; newDetail.localContactID = contact.localContactID; status = mDb.addContactDetail(newDetail); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting contact detail without unique ID"); status = mDb.deleteContactDetail(contact.details.get(0).localDetailID); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Deleting contact detail with unique ID"); status = mDb.deleteContactDetail(newDetail.localDetailID); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(1, State.DELETE_CONTACT_DETAIL_LIST); assertEquals(State.IDLE, mState); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } @Suppress // Breaks tests public void testRunWithAddDeleteGroupChange() { final String fnName = "testRunWithAddDeleteGroupChange"; Log.i(LOG_TAG, "***** EXECUTING " + fnName + " *****"); mTestStep = 1; startSubTest(fnName, "Checking change list is empty"); long noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Adding test contact to database"); Contact contact = mTestModule.createDummyContactData(); contact.contactID = TestModule.generateRandomLong(); contact.userID = generateTestUserID(contact.contactID); List<Contact> contactList = new ArrayList<Contact>(); contact.groupList.clear(); contactList.add(contact); ServiceStatus status = mDb.syncAddContactList(contactList, false, false); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Adding group to contact"); status = mDb.addContactToGroup(contact.localContactID, TEST_GROUP_1); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Removing group from contact"); status = mDb.deleteContactFromGroup(contact.localContactID, TEST_GROUP_1); assertEquals(ServiceStatus.SUCCESS, status); startSubTest(fnName, "Running processor"); runProcessor(0, State.IDLE); assertEquals(State.IDLE, mState); noOfChanges = ContactChangeLogTable.fetchNoOfContactDetailChanges(null, mDb .getReadableDatabase()); assertEquals(0, noOfChanges); noOfChanges = ContactDetailsTable.syncNativeFetchNoOfChanges(mDb.getReadableDatabase()); assertEquals(0, noOfChanges); startSubTest(fnName, "Running processor with no contact changes"); runProcessor(0, State.IDLE); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, fnName + " has completed successfully"); Log.i(LOG_TAG, "*************************************************************************"); Log.i(LOG_TAG, ""); } }