Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,28 @@ package at.bitfire.ical4android
import android.accounts.Account
import android.content.ContentProviderClient
import android.content.ContentUris
import android.os.Build
import android.provider.CalendarContract.ACCOUNT_TYPE_LOCAL
import android.provider.CalendarContract.AUTHORITY
import android.provider.CalendarContract.Events
import androidx.core.content.contentValuesOf
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import at.bitfire.ical4android.impl.TestCalendar
import at.bitfire.ical4android.util.MiscUtils.asSyncAdapter
import at.bitfire.ical4android.util.MiscUtils.closeCompat
import at.bitfire.synctools.icalendar.Css3Color
import at.bitfire.synctools.storage.calendar.AndroidCalendar
import at.bitfire.synctools.test.InitCalendarProviderRule
import net.fortuna.ical4j.model.Date
import net.fortuna.ical4j.model.DateList
import net.fortuna.ical4j.model.DateTime
import net.fortuna.ical4j.model.component.VAlarm
import net.fortuna.ical4j.model.parameter.Value
import net.fortuna.ical4j.model.property.Attendee
import net.fortuna.ical4j.model.property.DtEnd
import net.fortuna.ical4j.model.property.DtStart
import net.fortuna.ical4j.model.property.ExDate
import net.fortuna.ical4j.model.property.Organizer
import net.fortuna.ical4j.model.property.RRule
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.assertNotEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Rule
import org.junit.Test
Expand All @@ -61,7 +52,7 @@ class AndroidEventTest {
val context = getInstrumentation().targetContext
client = context.contentResolver.acquireContentProviderClient(AUTHORITY)!!

calendar = TestCalendar.findOrCreate(testAccount, client)
calendar = TestCalendar.findOrCreate(testAccount, client, withColors = true)
}

@After
Expand Down Expand Up @@ -209,7 +200,6 @@ class AndroidEventTest {
}



@Test
fun testTransaction() {
val event = Event()
Expand All @@ -229,240 +219,4 @@ class AndroidEventTest {
}
}


// companion object

@Test
fun testMarkEventAsDeleted() {
// Create event
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "A fine event"
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

// Delete event
AndroidEvent.markAsDeleted(client, testAccount, localEvent.id!!)

// Get the status of whether the event is deleted
client.query(
ContentUris.withAppendedId(Events.CONTENT_URI, localEvent.id!!).asSyncAdapter(testAccount),
arrayOf(Events.DELETED),
null,
null, null
)!!.use { cursor ->
cursor.moveToFirst()
assertEquals(1, cursor.getInt(0))
}
}


@Test
fun testNumDirectInstances_SingleInstance() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 1 instance"
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertEquals(1, AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumDirectInstances_Recurring() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 5 instances"
rRules.add(RRule("FREQ=DAILY;COUNT=5"))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertEquals(5, AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumDirectInstances_Recurring_Endless() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event without end"
rRules.add(RRule("FREQ=DAILY"))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertNull(AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
}

@Test
// flaky, needs InitCalendarProviderRule
fun testNumDirectInstances_Recurring_LateEnd() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 53 years"
rRules.add(RRule("FREQ=YEARLY;UNTIL=20740119T010203Z")) // year 2074 is not supported by Android <11 Calendar Storage
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
assertEquals(52, AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
else
assertNull(AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumDirectInstances_Recurring_ManyInstances() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 2 years"
rRules.add(RRule("FREQ=DAILY;UNTIL=20240120T010203Z"))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()
val number = AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!)

// Some android versions (i.e. <=Q and S) return 365*2 instances (wrong, 365*2+1 => correct),
// but we are satisfied with either result for now
assertTrue(number == 365 * 2 || number == 365 * 2 + 1)
}

@Test
fun testNumDirectInstances_RecurringWithExdate() {
val event = Event().apply {
dtStart = DtStart(Date("20220120T010203Z"))
summary = "Event with 5 instances"
rRules.add(RRule("FREQ=DAILY;COUNT=5"))
exDates.add(ExDate(DateList("20220121T010203Z", Value.DATE_TIME)))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertEquals(4, AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumDirectInstances_RecurringWithExceptions() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 5 instances"
rRules.add(RRule("FREQ=DAILY;COUNT=5"))
exceptions.add(Event().apply {
recurrenceId = RecurrenceId("20220122T010203Z")
dtStart = DtStart("20220122T130203Z")
summary = "Exception on 3rd day"
})
exceptions.add(Event().apply {
recurrenceId = RecurrenceId("20220124T010203Z")
dtStart = DtStart("20220122T160203Z")
summary = "Exception on 5th day"
})
}
val localEvent = AndroidEvent(calendar, event, "filename.ics", null, null, 0)
localEvent.add()

assertEquals(5 - 2, AndroidEvent.numDirectInstances(client, testAccount, localEvent.id!!))
}


@Test
fun testNumInstances_SingleInstance() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 1 instance"
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertEquals(1, AndroidEvent.numInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumInstances_Recurring() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 5 instances"
rRules.add(RRule("FREQ=DAILY;COUNT=5"))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertEquals(5, AndroidEvent.numInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumInstances_Recurring_Endless() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with infinite instances"
rRules.add(RRule("FREQ=YEARLY"))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertNull(AndroidEvent.numInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumInstances_Recurring_LateEnd() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event over 22 years"
rRules.add(RRule("FREQ=YEARLY;UNTIL=20740119T010203Z")) // year 2074 not supported by Android <11 Calendar Storage
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
assertEquals(52, AndroidEvent.numInstances(client, testAccount, localEvent.id!!))
else
assertNull(AndroidEvent.numInstances(client, testAccount, localEvent.id!!))
}

@Test
fun testNumInstances_Recurring_ManyInstances() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event over two years"
rRules.add(RRule("FREQ=DAILY;UNTIL=20240120T010203Z"))
}
val localEvent = AndroidEvent(calendar, event, null, null, null, 0)
localEvent.add()

assertEquals(
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
365 * 2 // Android <9: does not include UNTIL (incorrect!)
else
365 * 2 + 1, // Android ≥10: includes UNTIL (correct)
AndroidEvent.numInstances(client, testAccount, localEvent.id!!)
)
}

@Test
fun testNumInstances_RecurringWithExceptions() {
val event = Event().apply {
dtStart = DtStart("20220120T010203Z")
summary = "Event with 6 instances"
rRules.add(RRule("FREQ=DAILY;COUNT=6"))
exceptions.add(Event().apply {
recurrenceId = RecurrenceId("20220122T010203Z")
dtStart = DtStart("20220122T130203Z")
summary = "Exception on 3rd day"
})
exceptions.add(Event().apply {
recurrenceId = RecurrenceId("20220124T010203Z")
dtStart = DtStart("20220122T160203Z")
summary = "Exception on 5th day"
})
}
val localEvent = AndroidEvent(calendar, event, "filename.ics", null, null, 0)
localEvent.add()

calendar.getEvent(localEvent.id!!)!!

assertEquals(6, AndroidEvent.numInstances(client, testAccount, localEvent.id!!))
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ import java.util.UUID

object TestCalendar {

fun findOrCreate(account: Account, client: ContentProviderClient): AndroidCalendar {
fun findOrCreate(account: Account, client: ContentProviderClient, withColors: Boolean = false): AndroidCalendar {
val provider = AndroidCalendarProvider(account, client)

// we use colors for testing
provider.provideCss3ColorIndices()
if (withColors)
provider.provideCss3ColorIndices()
else
provider.removeColorIndices()

return provider.findFirstCalendar( null, null)
?: provider.createAndGetCalendar(contentValuesOf(
Expand Down
Loading