package com.todoroo.astrid.sync; import java.util.ArrayList; import android.text.TextUtils; import com.todoroo.andlib.data.Property; import com.todoroo.andlib.data.Property.LongProperty; import com.todoroo.andlib.data.Table; import com.todoroo.andlib.data.TodorooCursor; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.sql.Query; import com.todoroo.andlib.utility.Preferences; import com.todoroo.astrid.actfm.sync.AstridNewSyncMigrator; import com.todoroo.astrid.dao.MetadataDao; import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria; import com.todoroo.astrid.dao.RemoteModelDao; import com.todoroo.astrid.data.Metadata; import com.todoroo.astrid.data.RemoteModel; import com.todoroo.astrid.data.SyncFlags; import com.todoroo.astrid.data.TagData; import com.todoroo.astrid.data.Task; import com.todoroo.astrid.tags.TaskToTagMetadata; public class AstridNewSyncMigrationTest extends NewSyncTestCase { private static final LongProperty TASK_REMOTE_ID_FIELD = new LongProperty(Task.TABLE, RemoteModel.UUID_PROPERTY_NAME); private static final LongProperty TAG_REMOTE_ID_FIELD = new LongProperty(TagData.TABLE, RemoteModel.UUID_PROPERTY_NAME); @Autowired private MetadataDao metadataDao; public void testAstridSyncMigration() { setupOldDatabase(); Preferences.setBoolean(AstridNewSyncMigrator.PREF_SYNC_MIGRATION, false); new AstridNewSyncMigrator().performMigration(); assertAllModelsHaveUUID(); assertAllTagsHaveTagData(); assertAllMetadataHasAllFields(); } private void setupOldDatabase() { // Init 5 unsynced tasks and tags for (int i = 1; i <= 5; i++) { Task task = createTask("Task " + i, true); task.setValue(TASK_REMOTE_ID_FIELD, null); taskDao.save(task); TagData tag = createTagData("Tag " + i, true); tag.setValue(TAG_REMOTE_ID_FIELD, null); tagDataDao.saveExisting(tag); } Metadata m = new Metadata(); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 1L); m.setValue(TaskToTagMetadata.TAG_NAME, "Tag 1"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); m.clear(); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 2L); m.setValue(TaskToTagMetadata.TAG_NAME, "New tag"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); m.clear(); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 3L); m.setValue(TaskToTagMetadata.TAG_NAME, "Tag 3"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); m.clear(); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 3L); m.setValue(TaskToTagMetadata.TAG_NAME, "Tag 4"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); m.clear(); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 5L); m.setValue(TaskToTagMetadata.TAG_NAME, "Tag 1"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); m.clear(); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 5L); m.setValue(TaskToTagMetadata.TAG_NAME, "Tag 5"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); m.setValue(Metadata.KEY, TaskToTagMetadata.KEY); m.setValue(Metadata.TASK, 5L); m.setValue(TaskToTagMetadata.TAG_NAME, "New tag 2"); m.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); metadataDao.createNew(m); // State (task: tags) // Task 1: Tag 1 // Task 2: New tag // Task 3: Tag 3, Tag 4 // Task 4: (nothing) // Task 5: Tag 5, New tag 2 } private void assertAllModelsHaveUUID() { assertUUIDs(Task.TABLE, new Task(), taskDao, Task.ID, Task.UUID); assertUUIDs(TagData.TABLE, new TagData(), tagDataDao, TagData.ID, TagData.UUID); } private <TYPE extends RemoteModel> void assertUUIDs(Table table, TYPE instance, RemoteModelDao<TYPE> dao, Property<?>... properties) { TodorooCursor<TYPE> cursor = dao.query(Query.select(properties).from(table)); try { for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) { instance.clear(); instance.readPropertiesFromCursor(cursor); String uuid = instance.getValue(RemoteModel.UUID_PROPERTY); if (uuid == null || RemoteModel.NO_UUID.equals(uuid)) { fail(instance.getClass().getName() + " " + instance.getId() + " didn't have a uuid"); } } } finally { cursor.close(); } } private void assertAllTagsHaveTagData() { ArrayList<String> names = new ArrayList<String>(); for (int i = 1; i <= 5; i++) { String name = "Tag " + i; names.add(name); } names.add("New tag"); names.add("New tag 2"); String[] namesArray = names.toArray(new String[names.size()]); TodorooCursor<TagData> tagData = tagDataDao.query(Query.select(TagData.NAME).where(TagData.NAME.in(namesArray))); try { assertEquals(namesArray.length, tagData.getCount()); } finally { tagData.close(); } } private void assertAllMetadataHasAllFields() { TodorooCursor<Metadata> tagMetadata = metadataDao.query(Query.select(Metadata.PROPERTIES) .where(MetadataCriteria.withKey(TaskToTagMetadata.KEY))); try { assertEquals(tagMetadata.getCount(), 7); Metadata m = new Metadata(); for (tagMetadata.moveToFirst(); !tagMetadata.isAfterLast(); tagMetadata.moveToNext()) { m.readFromCursor(tagMetadata); assertTrue(!TextUtils.isEmpty(m.getValue(TaskToTagMetadata.TAG_NAME))); assertTrue(!RemoteModel.NO_UUID.equals(m.getValue(TaskToTagMetadata.TASK_UUID))); assertTrue(!RemoteModel.NO_UUID.equals(m.getValue(TaskToTagMetadata.TAG_UUID))); } } finally { tagMetadata.close(); } } }