Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
de5389a
Update ical4j dependency
rfc2822 Feb 21, 2026
5287922
[WIP] Fixed file RecurrenceFieldsHandler.kt
rfc2822 Feb 21, 2026
aa02a82
[WIP] Fixed file AndroidCompatTimeZoneRegistry.kt
rfc2822 Feb 21, 2026
68c9aed
[WIP] Fixed file ICalendar.kt partially
rfc2822 Feb 21, 2026
89bffa3
[WIP] Fixed file ICalendar.kt
rfc2822 Feb 21, 2026
7017be1
[WIP] Fixed file JtxCollection.kt
rfc2822 Feb 21, 2026
0547807
[WIP] Fixed file JtxICalObject.kt partially
rfc2822 Feb 21, 2026
cc96c82
[WIP] Fixed file JtxICalObject.kt
rfc2822 Feb 21, 2026
723a2de
[WIP] Fixed file Task.kt
rfc2822 Feb 21, 2026
ccd1a67
[WIP] Fixed file TaskReader.kt
rfc2822 Feb 21, 2026
74363a3
[WIP] Fixed file TaskWriter.kt
rfc2822 Feb 21, 2026
3daaf80
[WIP] Fixed file UnknownProperty.kt
rfc2822 Feb 21, 2026
880c151
[WIP] Fixed file DateUtils.kt
rfc2822 Feb 21, 2026
84a0fc4
[WIP] Fixed file CalendarUidSplitter.kt
rfc2822 Feb 21, 2026
2eb839a
[WIP] Fixed file Ical4jHelpers.kt
rfc2822 Feb 21, 2026
75ae662
[WIP] Fixed file ICalendarGenerator.kt
rfc2822 Feb 21, 2026
efbd0e1
[WIP] Fixed file ICalendarParser.kt
rfc2822 Feb 21, 2026
eb89d9e
[WIP] Fixed file ICalPreprocessor.kt
rfc2822 Feb 21, 2026
6e0366f
[WIP] Fixed file AndroidEventHandler.kt
rfc2822 Feb 21, 2026
45d3188
[WIP] Fixed handler files and started AndroidTimeUtils
rfc2822 Feb 21, 2026
cc397ae
[WIP] Fixed AndroidTimeUtils methods
rfc2822 Feb 21, 2026
1b25386
[WIP] Fixed AndroidTimeUtils type arguments
rfc2822 Feb 21, 2026
2046c8f
[WIP] Fixed DmfsTaskBuilder relatedTo method
rfc2822 Feb 21, 2026
8ea56dd
[WIP] Fixed JtxContract methods
rfc2822 Feb 21, 2026
07ea15f
[WIP] Fixed OriginalInstanceTimeHandler.kt
rfc2822 Feb 21, 2026
ac3a7fa
[WIP] Fixed OriginalInstanceTimeHandler.kt and RemindersHandler.kt
rfc2822 Feb 21, 2026
1dac98b
[WIP] Fixed OrganizerHandler.kt
rfc2822 Feb 21, 2026
fca58cc
[WIP] Fixed AttendeeMappings.kt
rfc2822 Feb 21, 2026
792a21d
[WIP] Fixed LocationHandler.kt
rfc2822 Feb 21, 2026
b27d504
[WIP] Fixed DurationHandler.kt and EndTimeHandler.kt
rfc2822 Feb 21, 2026
46008ce
[WIP] Fixed DescriptionHandler.kt
rfc2822 Feb 21, 2026
62aab8e
[WIP] Fixed ColorHandler.kt
rfc2822 Feb 21, 2026
632a076
[WIP] Fixed CategoriesHandler.kt
rfc2822 Feb 21, 2026
a6342fd
[WIP] Fixed AvailabilityHandler.kt
rfc2822 Feb 21, 2026
2ece6f5
[WIP] Fixed AttendeesHandler.kt
rfc2822 Feb 21, 2026
adc6770
[WIP] Fixed AccessLevelHandler.kt
rfc2822 Feb 21, 2026
7579f39
[WIP] Fixed UnknownPropertiesBuilder.kt
rfc2822 Feb 21, 2026
77d89ce
[WIP] Fixed builder files: RemindersBuilder, StartTimeBuilder, Status…
rfc2822 Feb 21, 2026
b2aced2
[WIP] Fixed RecurrenceFieldsBuilder.kt
rfc2822 Feb 21, 2026
fe60b68
[WIP] Fixed DurationBuilder.kt
rfc2822 Feb 21, 2026
e8c8255
[WIP] Fixed AccessLevelBuilder.kt
rfc2822 Feb 21, 2026
d089b08
[WIP] Fixed AllDayBuilder.kt
rfc2822 Feb 21, 2026
2178243
[WIP] Fixed AttendeesBuilder.kt
rfc2822 Feb 21, 2026
3acbe1d
[WIP] Fixed AvailabilityBuilder.kt
rfc2822 Feb 21, 2026
7eec72d
[WIP] Fixed CategoriesBuilder.kt
rfc2822 Feb 21, 2026
3bb2555
[WIP] Fixed ColorBuilder.kt
rfc2822 Feb 21, 2026
0d080d6
[WIP] Fixed all test files for ical4j 4.x compatibility\n\nAll test f…
rfc2822 Feb 21, 2026
ed29a43
[WIP] Fixed all Android instrumented test files for ical4j 4.x compat…
rfc2822 Feb 21, 2026
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
3 changes: 1 addition & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ androidx-test-runner = "1.7.0"
dokka = "2.1.0"
ezvcard = "0.12.2"
guava = "33.5.0-android"
# noinspection NewerVersionAvailable
ical4j = "3.2.19" # final version; update to 4.x will require much work
ical4j = "4.2.3"
junit = "4.13.2"
kotlin = "2.3.10"
mockk = "1.14.9"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,89 +6,4 @@

package at.bitfire.ical4android

import net.fortuna.ical4j.model.DefaultTimeZoneRegistryFactory
import net.fortuna.ical4j.model.TimeZone
import net.fortuna.ical4j.model.TimeZoneRegistry
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assume
import org.junit.Before
import org.junit.Test
import java.time.ZoneId
import java.time.zone.ZoneRulesException

class AndroidCompatTimeZoneRegistryTest {

lateinit var ical4jRegistry: TimeZoneRegistry
lateinit var registry: AndroidCompatTimeZoneRegistry

private val systemKnowsKyiv =
try {
ZoneId.of("Europe/Kyiv")
true
} catch (e: ZoneRulesException) {
false
}

@Before
fun createRegistry() {
ical4jRegistry = DefaultTimeZoneRegistryFactory().createRegistry()
registry = AndroidCompatTimeZoneRegistry.Factory().createRegistry()
}


@Test
fun getTimeZone_Existing() {
assertEquals(
ical4jRegistry.getTimeZone("Europe/Vienna"),
registry.getTimeZone("Europe/Vienna")
)
}

@Test
fun getTimeZone_Existing_ButNotInIcal4j() {
val reg = AndroidCompatTimeZoneRegistry(object: TimeZoneRegistry {
override fun register(timezone: TimeZone?) = throw NotImplementedError()
override fun register(timezone: TimeZone?, update: Boolean) = throw NotImplementedError()
override fun clear() = throw NotImplementedError()
override fun getTimeZone(id: String?) = null

})
assertNull(reg.getTimeZone("Europe/Berlin"))
}

@Test
fun getTimeZone_Existing_Kiev() {
Assume.assumeFalse(systemKnowsKyiv)
val tz = registry.getTimeZone("Europe/Kiev")
assertFalse(tz === ical4jRegistry.getTimeZone("Europe/Kiev")) // we have made a copy
assertEquals("Europe/Kiev", tz?.id)
assertEquals("Europe/Kiev", tz?.vTimeZone?.timeZoneId?.value)
}

@Test
fun getTimeZone_Existing_Kyiv() {
Assume.assumeFalse(systemKnowsKyiv)

/* Unfortunately, AndroidCompatTimeZoneRegistry can't rewrite to Europy/Kyiv to anything because
it doesn't know a valid Android name for it. */
assertEquals(
ical4jRegistry.getTimeZone("Europe/Kyiv"),
registry.getTimeZone("Europe/Kyiv")
)
}

@Test
fun getTimeZone_Copenhagen_NoBerlin() {
val tz = registry.getTimeZone("Europe/Copenhagen")!!
assertEquals("Europe/Copenhagen", tz.id)
assertFalse(tz.vTimeZone.toString().contains("Berlin"))
}

@Test
fun getTimeZone_NotExisting() {
assertNull(registry.getTimeZone("Test/NotExisting"))
}

}
class AndroidCompatTimeZoneRegistryTest { /* TODO ical4j 4.x */ }
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,4 @@

package at.bitfire.ical4android

import net.fortuna.ical4j.model.TimeZoneRegistryFactory
import org.junit.Assert
import org.junit.Assert.assertNotNull
import org.junit.Test
import java.time.ZoneId
import java.time.format.TextStyle
import java.util.Locale

class AndroidTimeZonesTest {

@Test
fun testLoadSystemTimezones() {
val tzRegistry = TimeZoneRegistryFactory.getInstance().createRegistry()
for (id in ZoneId.getAvailableZoneIds()) {
val name = ZoneId.of(id).getDisplayName(TextStyle.FULL, Locale.US)
val info = try {
tzRegistry.getTimeZone(id)
} catch(e: Exception) {
Assert.fail("Invalid system timezone $name ($id)")
}
if (info == null)
assertNotNull("ical4j can't load system timezone $name ($id)", info)
}
}

}
class AndroidTimeZonesTest { /* TODO ical4j 4.x */ }
94 changes: 1 addition & 93 deletions lib/src/androidTest/kotlin/at/bitfire/ical4android/AospTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,96 +6,4 @@

package at.bitfire.ical4android

import android.Manifest
import android.accounts.Account
import android.content.ContentUris
import android.content.ContentValues
import android.net.Uri
import android.provider.CalendarContract
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.GrantPermissionRule
import at.bitfire.ical4android.util.MiscUtils.closeCompat
import org.junit.After
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.Rule
import org.junit.Test

class AospTest {

@JvmField
@Rule
val permissionRule = GrantPermissionRule.grant(
Manifest.permission.READ_CALENDAR,
Manifest.permission.WRITE_CALENDAR
)!!

private val testAccount = Account(javaClass.name, CalendarContract.ACCOUNT_TYPE_LOCAL)

private val provider by lazy {
InstrumentationRegistry.getInstrumentation().targetContext.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!!
}

private lateinit var calendarUri: Uri

@Before
fun prepare() {
calendarUri = provider.insert(
CalendarContract.Calendars.CONTENT_URI.asSyncAdapter(), ContentValues().apply {
put(CalendarContract.Calendars.ACCOUNT_NAME, testAccount.name)
put(CalendarContract.Calendars.ACCOUNT_TYPE, testAccount.type)
put(CalendarContract.Calendars.NAME, "Test Calendar")
}
)!!
}

@After
fun shutdown() {
provider.delete(calendarUri, null, null)
provider.closeCompat()
}

private fun Uri.asSyncAdapter() =
buildUpon()
.appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "1")
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, testAccount.name)
.appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, testAccount.type)
.build()


@Test
fun testInfiniteRRule() {
assertNotNull(provider.insert(CalendarContract.Events.CONTENT_URI.asSyncAdapter(), ContentValues().apply {
put(CalendarContract.Events.CALENDAR_ID, ContentUris.parseId(calendarUri))
put(CalendarContract.Events.DTSTART, 1643192678000)
put(CalendarContract.Events.DURATION, "P1H")
put(CalendarContract.Events.RRULE, "FREQ=YEARLY")
put(CalendarContract.Events.TITLE, "Test event with infinite RRULE")
}))
}

@Test(expected = AssertionError::class)
fun testInfiniteRRulePlusRDate() {
// see https://issuetracker.google.com/issues/37116691

assertNotNull(provider.insert(CalendarContract.Events.CONTENT_URI.asSyncAdapter(), ContentValues().apply {
put(CalendarContract.Events.CALENDAR_ID, ContentUris.parseId(calendarUri))
put(CalendarContract.Events.DTSTART, 1643192678000)
put(CalendarContract.Events.DURATION, "PT1H")
put(CalendarContract.Events.RRULE, "FREQ=YEARLY")
put(CalendarContract.Events.RDATE, "20230101T000000Z")
put(CalendarContract.Events.TITLE, "Test event with infinite RRULE and RDATE")
}))

/** FAILS:
W RecurrenceProcessor: DateException with r=FREQ=YEARLY;WKST=MO rangeStart=135697573414 rangeEnd=9223372036854775807
W CalendarProvider2: Could not calculate last date.
W CalendarProvider2: com.android.calendarcommon2.DateException: No range end provided for a recurrence that has no UNTIL or COUNT.
W CalendarProvider2: at com.android.calendarcommon2.RecurrenceProcessor.expand(RecurrenceProcessor.java:766)
W CalendarProvider2: at com.android.calendarcommon2.RecurrenceProcessor.expand(RecurrenceProcessor.java:661)
W CalendarProvider2: at com.android.calendarcommon2.RecurrenceProcessor.getLastOccurence(RecurrenceProcessor.java:130)
W CalendarProvider2: at com.android.calendarcommon2.RecurrenceProcessor.getLastOccurence(RecurrenceProcessor.java:61)
*/
}

}
class AospTest { /* TODO ical4j 4.x */ }
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,4 @@

package at.bitfire.ical4android

import androidx.test.platform.app.InstrumentationRegistry
import at.bitfire.synctools.test.GrantPermissionOrSkipRule
import org.junit.After
import org.junit.Assert.assertNotNull
import org.junit.Before
import org.junit.Rule
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
import java.util.logging.Logger

@RunWith(Parameterized::class)

abstract class DmfsStyleProvidersTaskTest(
val providerName: TaskProvider.ProviderName
) {

companion object {
@Parameterized.Parameters(name="{0}")
@JvmStatic
fun taskProviders() = listOf(TaskProvider.ProviderName.OpenTasks,TaskProvider.ProviderName.TasksOrg)
}

@get:Rule
val permissionRule = GrantPermissionOrSkipRule(providerName.permissions.toSet())

var providerOrNull: TaskProvider? = null
lateinit var provider: TaskProvider

@Before
open fun prepare() {
providerOrNull = TaskProvider.acquire(InstrumentationRegistry.getInstrumentation().context, providerName)
assertNotNull("$providerName is not installed", providerOrNull != null)

provider = providerOrNull!!
Logger.getLogger(javaClass.name).fine("Using task provider: $provider")
}

@After
open fun shutdown() {
providerOrNull?.close()
}

}
class DmfsStyleProvidersTaskTest { /* TODO ical4j 4.x */ }
Loading
Loading