Handle null cases for Events.DIRTY (#1663)

* Handled nullity of `Calendar.dirty`

* Fixed ids

* Use multiline SQL queries

* Fix kdoc links

* Improve kdoc

* Fix capitalization

* Simplify kdoc

* Improved `LocalCalendarTest`
This commit is contained in:
Arnau Mora
2025-08-28 11:25:57 +02:00
committed by GitHub
parent 44666d2138
commit cd725479cd
3 changed files with 83 additions and 17 deletions

View File

@@ -29,6 +29,7 @@ import net.fortuna.ical4j.model.property.RecurrenceId
import net.fortuna.ical4j.model.property.Status
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Before
import org.junit.Rule
@@ -159,21 +160,77 @@ class LocalCalendarTest {
}
}
@Test
fun testRemoveNotDirtyMarked_IdLargerThanIntMaxValue() {
val id = androidCalendar.addEvent(Entity(contentValuesOf(
Events.CALENDAR_ID to androidCalendar.id,
Events._ID to Int.MAX_VALUE.toLong() + 10,
Events.DTSTART to System.currentTimeMillis(),
Events.DTEND to System.currentTimeMillis(),
Events.TITLE to "Some Event",
Events.DIRTY to 0,
AndroidEvent2.COLUMN_FLAGS to 123
)))
/**
* Verifies that [LocalCalendar.removeNotDirtyMarked] works as expected.
* @param contentValues values to set on the event. Required:
* - [Events._ID]
* - [Events.DIRTY]
*/
private fun testRemoveNotDirtyMarked(contentValues: ContentValues) {
val id = androidCalendar.addEvent(Entity(
contentValuesOf(
Events.CALENDAR_ID to androidCalendar.id,
Events.DTSTART to System.currentTimeMillis(),
Events.DTEND to System.currentTimeMillis(),
Events.TITLE to "Some Event",
AndroidEvent2.COLUMN_FLAGS to 123
).apply { putAll(contentValues) }
))
calendar.removeNotDirtyMarked(123)
assertNull(androidCalendar.getEvent(id))
}
@Test
fun testRemoveNotDirtyMarked_IdLargerThanIntMaxValue() = testRemoveNotDirtyMarked(
contentValuesOf(Events._ID to Int.MAX_VALUE.toLong() + 10, Events.DIRTY to 0)
)
@Test
fun testRemoveNotDirtyMarked_DirtyIs0() = testRemoveNotDirtyMarked(
contentValuesOf(Events._ID to 1, Events.DIRTY to 0)
)
@Test
fun testRemoveNotDirtyMarked_DirtyNull() = testRemoveNotDirtyMarked(
contentValuesOf(Events._ID to 1, Events.DIRTY to null)
)
/**
* Verifies that [LocalCalendar.markNotDirty] works as expected.
* @param contentValues values to set on the event. Required:
* - [Events.DIRTY]
*/
private fun testMarkNotDirty(contentValues: ContentValues) {
val id = androidCalendar.addEvent(Entity(
contentValuesOf(
Events.CALENDAR_ID to androidCalendar.id,
Events._ID to 1,
Events.DTSTART to System.currentTimeMillis(),
Events.DTEND to System.currentTimeMillis(),
Events.TITLE to "Some Event",
AndroidEvent2.COLUMN_FLAGS to 123
).apply { putAll(contentValues) }
))
val updated = calendar.markNotDirty(321)
assertEquals(1, updated)
assertEquals(321, androidCalendar.getEvent(id)?.flags)
}
@Test
fun test_markNotDirty_DirtyIs0() = testMarkNotDirty(
contentValuesOf(
Events.DIRTY to 0
)
)
@Test
fun test_markNotDirty_DirtyIsNull() = testMarkNotDirty(
contentValuesOf(
Events.DIRTY to null
)
)
}

View File

@@ -107,7 +107,12 @@ class LocalCalendar @AssistedInject constructor(
override fun markNotDirty(flags: Int) =
androidCalendar.updateEventRows(
contentValuesOf(AndroidEvent2.COLUMN_FLAGS to flags),
"${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL",
// `dirty` can be 0, 1, or null. "NOT dirty" is not enough.
"""
${Events.CALENDAR_ID}=?
AND (${Events.DIRTY} IS NULL OR ${Events.DIRTY}=0)
AND ${Events.ORIGINAL_ID} IS NULL
""".trimIndent(),
arrayOf(androidCalendar.id.toString())
)
@@ -116,7 +121,13 @@ class LocalCalendar @AssistedInject constructor(
val batch = CalendarBatchOperation(androidCalendar.client)
androidCalendar.iterateEventRows(
arrayOf(Events._ID),
"${Events.CALENDAR_ID}=? AND NOT ${Events.DIRTY} AND ${Events.ORIGINAL_ID} IS NULL AND ${AndroidEvent2.COLUMN_FLAGS}=?",
// `dirty` can be 0, 1, or null. "NOT dirty" is not enough.
"""
${Events.CALENDAR_ID}=?
AND (${Events.DIRTY} IS NULL OR ${Events.DIRTY}=0)
AND ${Events.ORIGINAL_ID} IS NULL
AND ${AndroidEvent2.COLUMN_FLAGS}=?
""".trimIndent(),
arrayOf(androidCalendar.id.toString(), flags.toString())
) { values ->
val id = values.getAsLong(Events._ID)

View File

@@ -49,8 +49,7 @@ interface LocalCollection<out T: LocalResource<*>> {
fun findByName(name: String): T?
/**
* Sets the [LocalEvent.COLUMN_FLAGS] value for entries which are not dirty ([Events.DIRTY] is 0)
* and have an [Events.ORIGINAL_ID] of null.
* Updates the flags value for entries which are not dirty.
*
* @param flags value of flags to set (for instance, [LocalResource.FLAG_REMOTELY_PRESENT]])
*
@@ -59,8 +58,7 @@ interface LocalCollection<out T: LocalResource<*>> {
fun markNotDirty(flags: Int): Int
/**
* Removes entries which are not dirty ([Events.DIRTY] is 0 and an [Events.ORIGINAL_ID] is null) with
* a given flag combination.
* Removes entries which are not dirty with a given flag combination.
*
* @param flags exact flags value to remove entries with (for instance, if this is [LocalResource.FLAG_REMOTELY_PRESENT]],
* all entries with exactly this flag will be removed)