Add tests for 11.3 migration

pull/1309/head
Alex Baker 5 years ago
parent 20f74bec33
commit 137a27432a

@ -0,0 +1,243 @@
@file:Suppress("ClassName")
package com.todoroo.astrid.service
import android.content.ContentProviderResult
import at.bitfire.ical4android.BatchOperation
import com.natpryce.makeiteasy.MakeItEasy.with
import com.todoroo.astrid.data.Task
import com.todoroo.astrid.helper.UUIDHelper
import dagger.hilt.android.testing.HiltAndroidTest
import dagger.hilt.android.testing.UninstallModules
import kotlinx.coroutines.runBlocking
import org.dmfs.tasks.contract.TaskContract
import org.dmfs.tasks.contract.TaskContract.CALLER_IS_SYNCADAPTER
import org.dmfs.tasks.contract.TaskContract.TaskLists
import org.junit.Test
import org.tasks.SuspendFreeze.Companion.freezeAt
import org.tasks.TestUtilities.assertEquals
import org.tasks.TestUtilities.fromString
import org.tasks.data.*
import org.tasks.injection.InjectingTestCase
import org.tasks.injection.ProductionModule
import org.tasks.makers.CaldavTaskMaker.CALENDAR
import org.tasks.makers.CaldavTaskMaker.REMOTE_ID
import org.tasks.makers.CaldavTaskMaker.TASK
import org.tasks.makers.CaldavTaskMaker.VTODO
import org.tasks.makers.CaldavTaskMaker.newCaldavTask
import org.tasks.makers.TaskMaker.DUE_DATE
import org.tasks.makers.TaskMaker.HIDE_TYPE
import org.tasks.makers.TaskMaker.MODIFICATION_TIME
import org.tasks.makers.TaskMaker.newTask
import org.tasks.time.DateTime
import javax.inject.Inject
@UninstallModules(ProductionModule::class)
@HiltAndroidTest
class Upgrade_11_3_Test : InjectingTestCase() {
@Inject lateinit var taskDao: TaskDao
@Inject lateinit var caldavDao: CaldavDao
@Inject lateinit var openTaskDao: OpenTaskDao
@Inject lateinit var upgrader: Upgrade_11_3
@Test
fun applyRemoteiCalendarStartDate() = runBlocking {
val taskId = taskDao.insert(newTask())
caldavDao.insert(newCaldavTask(with(TASK, taskId), with(VTODO, VTODO_WITH_START_DATE)))
upgrader.applyiCalendarStartDates()
assertEquals(DateTime(2021, 1, 21), taskDao.fetch(taskId)?.hideUntil)
}
@Test
fun ignoreRemoteiCalendarStartDate() = runBlocking {
val taskId = taskDao.insert(newTask(
with(DUE_DATE, DateTime(2021, 1, 20)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE)
))
caldavDao.insert(newCaldavTask(with(TASK, taskId), with(VTODO, VTODO_WITH_START_DATE)))
upgrader.applyiCalendarStartDates()
assertEquals(DateTime(2021, 1, 20), taskDao.fetch(taskId)?.hideUntil)
}
@Test
fun touchTaskWithLocaliCalendarStartDate() = runBlocking {
val upgradeTime = DateTime(2021, 1, 21, 11, 47, 32, 450)
val taskId = taskDao.insert(newTask(
with(DUE_DATE, DateTime(2021, 1, 20)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE),
with(MODIFICATION_TIME, DateTime(2021, 1, 21, 9, 50, 4, 348))
))
caldavDao.insert(newCaldavTask(with(TASK, taskId), with(VTODO, VTODO_WITH_START_DATE)))
freezeAt(upgradeTime) {
upgrader.applyiCalendarStartDates()
}
assertEquals(upgradeTime, taskDao.fetch(taskId)?.modificationDate)
}
@Test
fun dontTouchWhenNoiCalendarStartDate() = runBlocking {
val modificationTime = DateTime(2021, 1, 21, 9, 50, 4, 348)
val taskId = taskDao.insert(newTask(with(MODIFICATION_TIME, modificationTime)))
caldavDao.insert(newCaldavTask(with(TASK, taskId), with(VTODO, VTODO_NO_START_DATE)))
upgrader.applyiCalendarStartDates()
assertEquals(modificationTime, taskDao.fetch(taskId)?.modificationDate)
}
@Test
fun applyRemoteOpenTaskStartDate() = runBlocking {
val (listId, list) = insertList()
applyOperation(
MyAndroidTask(fromString(VTODO_WITH_START_DATE))
.toBuilder(openTaskDao.tasks, true)
.withValue(TaskContract.TaskColumns.LIST_ID, listId)
)
val taskId = taskDao.insert(newTask())
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "4586964443060640060"),
with(TASK, taskId)
))
upgrader.applyOpenTaskStartDates()
assertEquals(DateTime(2021, 1, 21), taskDao.fetch(taskId)?.hideUntil)
}
@Test
fun ignoreRemoteOpenTaskStartDate() = runBlocking {
val (listId, list) = insertList()
applyOperation(
MyAndroidTask(fromString(VTODO_WITH_START_DATE))
.toBuilder(openTaskDao.tasks, true)
.withValue(TaskContract.TaskColumns.LIST_ID, listId)
)
val taskId = taskDao.insert(newTask(
with(DUE_DATE, DateTime(2021, 1, 20)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE)
))
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "4586964443060640060"),
with(TASK, taskId)
))
upgrader.applyOpenTaskStartDates()
assertEquals(DateTime(2021, 1, 20), taskDao.fetch(taskId)?.hideUntil)
}
@Test
fun touchWithOpenTaskStartDate() = runBlocking {
val upgradeTime = DateTime(2021, 1, 21, 11, 47, 32, 450)
val (listId, list) = insertList()
applyOperation(
MyAndroidTask(fromString(VTODO_WITH_START_DATE))
.toBuilder(openTaskDao.tasks, true)
.withValue(TaskContract.TaskColumns.LIST_ID, listId)
)
val taskId = taskDao.insert(newTask(
with(DUE_DATE, DateTime(2021, 1, 20)),
with(HIDE_TYPE, Task.HIDE_UNTIL_DUE),
with(MODIFICATION_TIME, DateTime(2021, 1, 21, 9, 50, 4, 348))
))
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "4586964443060640060"),
with(TASK, taskId)
))
freezeAt(upgradeTime) {
upgrader.applyOpenTaskStartDates()
}
assertEquals(upgradeTime, taskDao.fetch(taskId)?.modificationDate)
}
@Test
fun dontTouchNoOpenTaskStartDate() = runBlocking {
val modificationTime = DateTime(2021, 1, 21, 9, 50, 4, 348)
val (listId, list) = insertList()
applyOperation(
MyAndroidTask(fromString(VTODO_NO_START_DATE))
.toBuilder(openTaskDao.tasks, true)
.withValue(TaskContract.TaskColumns.LIST_ID, listId)
)
val taskId = taskDao.insert(newTask(with(MODIFICATION_TIME, modificationTime)))
caldavDao.insert(newCaldavTask(
with(CALENDAR, list.uuid),
with(REMOTE_ID, "4586964443060640060"),
with(TASK, taskId)
))
upgrader.applyOpenTaskStartDates()
assertEquals(modificationTime, taskDao.fetch(taskId)?.modificationDate)
}
private suspend fun insertList(
type: String = OpenTaskDao.ACCOUNT_TYPE_DAVx5,
account: String = "account"
): Pair<String, CaldavCalendar> {
val url = UUIDHelper.newUUID()
val uri = openTaskDao.taskLists.buildUpon()
.appendQueryParameter(CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(TaskLists.ACCOUNT_NAME, account)
.appendQueryParameter(TaskLists.ACCOUNT_TYPE, type)
.build()
val result = applyOperation(
BatchOperation.CpoBuilder.newInsert(uri)
.withValue(TaskContract.CommonSyncColumns._SYNC_ID, url)
.withValue(TaskLists.SYNC_ENABLED, "1")
)
return Pair(result.uri!!.lastPathSegment!!, CaldavCalendar().apply {
uuid = UUIDHelper.newUUID()
this.account = "$type:$account"
this.url = url
caldavDao.insert(this)
})
}
private fun applyOperation(build: BatchOperation.CpoBuilder): ContentProviderResult =
context.contentResolver.applyBatch(openTaskDao.authority, arrayListOf(build.build()))[0]
companion object {
val VTODO_WITH_START_DATE = """
BEGIN:VCALENDAR
VERSION:2.0
PRODID:+//IDN tasks.org//android-110301//EN
BEGIN:VTODO
DTSTAMP:20210121T153032Z
UID:4586964443060640060
CREATED:20210121T153000Z
LAST-MODIFIED:20210121T153029Z
SUMMARY:Test
PRIORITY:9
X-APPLE-SORT-ORDER:-27
DTSTART;VALUE=DATE:20210121
END:VTODO
END:VCALENDAR
""".trimIndent()
val VTODO_NO_START_DATE = """
BEGIN:VCALENDAR
VERSION:2.0
PRODID:+//IDN tasks.org//android-110301//EN
BEGIN:VTODO
DTSTAMP:20210121T153032Z
UID:4586964443060640060
CREATED:20210121T153000Z
LAST-MODIFIED:20210121T153029Z
SUMMARY:Test
PRIORITY:9
X-APPLE-SORT-ORDER:-27
END:VTODO
END:VCALENDAR
""".trimIndent()
}
}

@ -6,11 +6,18 @@ import com.todoroo.astrid.data.Task
import org.tasks.caldav.CaldavConverter
import org.tasks.data.CaldavTask
import org.tasks.preferences.Preferences
import org.tasks.time.DateTime
import java.io.StringReader
import java.nio.file.Files
import java.nio.file.Paths
object TestUtilities {
fun assertEquals(expected: Long, actual: DateTime) =
org.junit.Assert.assertEquals(expected, actual.millis)
fun assertEquals(expected: DateTime, actual: Long?) =
org.junit.Assert.assertEquals(expected.millis, actual)
fun newPreferences(context: Context): Preferences {
return Preferences(context, "test_preferences")
}
@ -39,7 +46,7 @@ object TestUtilities {
return String(Files.readAllBytes(paths), Charsets.UTF_8)
}
private fun fromString(task: String): at.bitfire.ical4android.Task =
fun fromString(task: String): at.bitfire.ical4android.Task =
tasksFromReader(StringReader(task))
.takeIf { it.size == 1 }
?.first()

@ -12,11 +12,13 @@ object CaldavTaskMaker {
val TASK: Property<CaldavTask, Long> = newProperty()
val REMOTE_ID: Property<CaldavTask, String?> = newProperty()
val REMOTE_PARENT: Property<CaldavTask, String?> = newProperty()
val VTODO: Property<CaldavTask, String?> = newProperty()
private val instantiator = Instantiator<CaldavTask> {
val task = CaldavTask(it.valueOf(TASK, 1L), it.valueOf(CALENDAR, "calendar"))
task.remoteId = it.valueOf(REMOTE_ID, task.remoteId)
task.remoteParent = it.valueOf(REMOTE_PARENT, null as String?)
task.vtodo = it.valueOf(VTODO, null as String?)
task
}

@ -21,6 +21,7 @@ object TaskMaker {
val RANDOM_REMINDER_PERIOD: Property<Task, Long> = newProperty()
val HIDE_TYPE: Property<Task, Int> = newProperty()
val REMINDERS: Property<Task, Int> = newProperty()
val MODIFICATION_TIME: Property<Task, DateTime> = newProperty()
val CREATION_TIME: Property<Task, DateTime> = newProperty()
val COMPLETION_TIME: Property<Task, DateTime> = newProperty()
val DELETION_TIME: Property<Task, DateTime?> = newProperty()
@ -89,7 +90,7 @@ object TaskMaker {
task.uuid = lookup.valueOf(UUID, NO_UUID)
val creationTime = lookup.valueOf(CREATION_TIME, DateTimeUtils.newDateTime())
task.creationDate = creationTime.millis
task.modificationDate = creationTime.millis
task.modificationDate = lookup.valueOf(MODIFICATION_TIME, creationTime).millis
task.parent = lookup.valueOf(PARENT, 0L)
task
}

@ -0,0 +1,55 @@
@file:Suppress("ClassName")
package com.todoroo.astrid.service
import org.tasks.caldav.iCalendar
import org.tasks.caldav.iCalendar.Companion.apply
import org.tasks.data.OpenTaskDao
import org.tasks.data.TaskDao
import org.tasks.data.UpgraderDao
import javax.inject.Inject
class Upgrade_11_3 @Inject constructor(
private val upgraderDao: UpgraderDao,
private val openTaskDao: OpenTaskDao,
private val taskDao: TaskDao
) {
internal suspend fun applyiCalendarStartDates() {
val (hasStartDate, noStartDate) =
upgraderDao.tasksWithVtodos().partition { it.startDate > 0 }
for (task in noStartDate) {
task.vtodo?.let { iCalendar.fromVtodo(it) }?.dtStart?.let {
it.apply(task.task)
upgraderDao.setStartDate(task.id, task.startDate)
}
}
hasStartDate
.map { it.id }
.let { taskDao.touch(it) }
}
internal suspend fun applyOpenTaskStartDates() {
openTaskDao.getLists().forEach { list ->
val (hasStartDate, noStartDate) =
upgraderDao
.getOpenTasksForList(list.account!!, list.url!!)
.partition { it.startDate > 0 }
for (task in noStartDate) {
openTaskDao
.getTask(list.id, task.remoteId!!)
?.dtStart
?.let {
it.apply(task.task)
upgraderDao.setStartDate(task.id, task.startDate)
}
}
hasStartDate
.map { it.id }
.let { taskDao.touch(it) }
}
}
companion object {
const val VERSION = 110300
}
}

@ -7,12 +7,12 @@ import com.google.common.collect.ListMultimap
import com.google.common.collect.Multimaps
import com.todoroo.astrid.api.GtasksFilter
import com.todoroo.astrid.dao.TaskDao
import dagger.Lazy
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.runBlocking
import org.tasks.R
import org.tasks.Strings.isNullOrEmpty
import org.tasks.caldav.iCalendar
import org.tasks.caldav.iCalendar.Companion.apply
import org.tasks.caldav.iCalendar.Companion.fromVtodo
import org.tasks.caldav.iCalendar.Companion.getParent
import org.tasks.caldav.iCalendar.Companion.order
@ -43,7 +43,7 @@ class Upgrader @Inject constructor(
private val widgetManager: AppWidgetManager,
private val taskMover: TaskMover,
private val upgraderDao: UpgraderDao,
private val openTaskDao: OpenTaskDao) {
private val upgrade_11_3: Lazy<Upgrade_11_3>) {
fun upgrade(from: Int, to: Int) {
if (from > 0) {
@ -72,10 +72,12 @@ class Upgrader @Inject constructor(
.filter { it.getSql().trim() == "WHERE" }
.forEach { filterDao.delete(it) }
}
run(from, V11_3) {
run(from, Upgrade_11_3.VERSION) {
with(upgrade_11_3.get()) {
applyiCalendarStartDates()
applyOpenTaskStartDates()
}
}
preferences.setBoolean(R.string.p_just_updated, true)
}
preferences.setCurrentVersion(to)
@ -122,39 +124,6 @@ class Upgrader @Inject constructor(
return getAndroidColor(context, index)
}
private suspend fun applyiCalendarStartDates() {
val (hasStartDate, noStartDate) = upgraderDao.tasksWithVtodos().partition { it.startDate > 0 }
for (task in noStartDate) {
task.vtodo?.let { fromVtodo(it) }?.dtStart?.let {
it.apply(task.task)
upgraderDao.setStartDate(task.id, task.startDate)
}
}
hasStartDate
.map { it.id }
.let { taskDao.touch(it) }
}
private suspend fun applyOpenTaskStartDates() {
openTaskDao.getLists().forEach { list ->
val (hasStartDate, noStartDate) =
upgraderDao
.getOpenTasksForList(list.account!!, list.url!!)
.partition { it.startDate > 0 }
for (task in noStartDate) {
openTaskDao
.getTask(list.id, task.remoteId!!)
?.dtStart
?.let {
it.apply(task.task)
upgraderDao.setStartDate(task.id, task.startDate)
}
}
hasStartDate
.map { it.id }
.let { taskDao.touch(it) }
}
}
private suspend fun applyCaldavOrder() {
for (task in upgraderDao.tasksWithVtodos().map(CaldavTaskContainer::caldavTask)) {
@ -357,7 +326,6 @@ class Upgrader @Inject constructor(
const val V9_7 = 90700
const val V9_7_3 = 90704
const val V10_0_2 = 100012
const val V11_3 = 110300
@JvmStatic
fun getAndroidColor(context: Context, index: Int): Int {

@ -6,6 +6,7 @@ import android.content.ContentProviderOperation.newInsert
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.net.Uri
import at.bitfire.ical4android.BatchOperation
import at.bitfire.ical4android.Task
import at.bitfire.ical4android.UnknownProperty
@ -28,7 +29,8 @@ class OpenTaskDao @Inject constructor(
) {
private val cr = context.contentResolver
val authority = context.getString(R.string.opentasks_authority)
val tasks = Tasks.getContentUri(authority)
val tasks: Uri = Tasks.getContentUri(authority)
val taskLists: Uri = TaskLists.getContentUri(authority)
private val properties = Properties.getContentUri(authority)
suspend fun newAccounts(): List<String> = getListsByAccount().newAccounts(caldavDao)
@ -39,7 +41,7 @@ class OpenTaskDao @Inject constructor(
suspend fun getLists(): List<CaldavCalendar> = withContext(Dispatchers.IO) {
val calendars = ArrayList<CaldavCalendar>()
cr.query(
TaskLists.getContentUri(authority),
taskLists,
null,
"${TaskListColumns.SYNC_ENABLED}=1 AND ($SUPPORTED_TYPE_FILTER)",
null,
@ -192,10 +194,7 @@ class OpenTaskDao @Inject constructor(
suspend fun getTask(listId: Long, uid: String): Task? = withContext(Dispatchers.IO) {
cr.query(
Tasks.getContentUri(authority)
.buildUpon()
.appendQueryParameter(LOAD_PROPERTIES, "1")
.build(),
tasks.buildUpon().appendQueryParameter(LOAD_PROPERTIES, "1").build(),
null,
"${Tasks.LIST_ID} = $listId AND ${Tasks._UID} = '$uid'",
null,
@ -210,7 +209,7 @@ class OpenTaskDao @Inject constructor(
companion object {
private const val OPENTASK_BATCH_LIMIT = 499
private const val ACCOUNT_TYPE_DAVx5 = "bitfire.at.davdroid"
const val ACCOUNT_TYPE_DAVx5 = "bitfire.at.davdroid"
private const val ACCOUNT_TYPE_ETESYNC = "com.etesync.syncadapter"
private const val ACCOUNT_TYPE_DECSYNC = "org.decsync.tasks"
val SUPPORTED_TYPES = setOf(

Loading…
Cancel
Save