Loading app/src/androidTest/java/at/bitfire/davdroid/InitCalendarProviderRule.kt +58 −37 Original line number Diff line number Diff line Loading @@ -4,11 +4,15 @@ package at.bitfire.davdroid import android.Manifest import android.accounts.Account import android.content.ContentUris import android.content.ContentValues import android.os.Build import android.provider.CalendarContract import androidx.annotation.RequiresApi import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.resource.LocalCalendar import at.bitfire.davdroid.resource.LocalEvent Loading @@ -16,29 +20,55 @@ import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.Event import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.RRule import org.junit.rules.RuleChain import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement /** * JUnit ClassRule which initializes the AOSP CalendarProvider * Needed for some "flaky" tests which would otherwise only succeed on second run * JUnit ClassRule which initializes the AOSP CalendarProvider. * Needed for some "flaky" tests which would otherwise only succeed on second run. * * Currently tested on development machine (Ryzen) with Android 12 images (with/without Google Play). * Calendar provider behaves quite randomly, so it may or may not work. If you (the reader * if this comment) can find out on how to initialize the calendar provider so that the * tests are reliably run after `adb shell pm clear com.android.providers.calendar`, * please let us know! * * If you run tests manually, just make sure to ignore the first run after the calendar * provider has been accessed the first time. */ class InitCalendarProviderRule : TestRule { class InitCalendarProviderRule private constructor(): TestRule { companion object { private val account = Account("LocalCalendarTest", CalendarContract.ACCOUNT_TYPE_LOCAL) private val context = InstrumentationRegistry.getInstrumentation().targetContext private val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! private val uri = AndroidCalendar.create(account, provider, ContentValues()) private val calendar = AndroidCalendar.findByID(account, provider, LocalCalendar.Factory, ContentUris.parseId(uri)) fun getInstance() = RuleChain .outerRule(GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)) .around(InitCalendarProviderRule()) } override fun apply(base: Statement, description: Description): Statement { Logger.log.info("Before test: ${description.displayName}") Logger.log.info("Initializing calendar provider before running ${description.displayName}") return InitCalendarProviderStatement(base) } Logger.log.info("Initializing CalendarProvider (InitCalendarProviderRule)") class InitCalendarProviderStatement(val base: Statement): Statement() { override fun evaluate() { if (Build.VERSION.SDK_INT < 31) Logger.log.warning("Calendar provider initialization may or may not work. See InitCalendarProviderRule") initCalendarProvider() base.evaluate() } private fun initCalendarProvider() { val account = Account("LocalCalendarTest", CalendarContract.ACCOUNT_TYPE_LOCAL) val context = InstrumentationRegistry.getInstrumentation().targetContext val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! val uri = AndroidCalendar.create(account, provider, ContentValues()) val calendar = AndroidCalendar.findByID(account, provider, LocalCalendar.Factory, ContentUris.parseId(uri)) try { // single event init val normalEvent = Event().apply { dtStart = DtStart("20220120T010203Z") Loading @@ -57,19 +87,10 @@ class InitCalendarProviderRule : TestRule { val localRecurringEvent = LocalEvent(calendar, recurringEvent, null, null, null, 0) localRecurringEvent.add() LocalEvent.numInstances(provider, account, localRecurringEvent.id!!) // Run test Logger.log.info("Evaluating test..") return try { object : Statement() { @Throws(Throwable::class) override fun evaluate() { base.evaluate() } } } finally { Logger.log.info("After test: $description") calendar.delete() } } } } No newline at end of file app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt +2 −6 Original line number Diff line number Diff line Loading @@ -31,12 +31,8 @@ class LocalCalendarTest { companion object { @JvmField @ClassRule(order = 0) val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)!! @JvmField @ClassRule(order = 1) val initCalendarProviderRule: TestRule = InitCalendarProviderRule() @ClassRule val initCalendarProviderRule: TestRule = InitCalendarProviderRule.getInstance() private lateinit var provider: ContentProviderClient Loading app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt +2 −6 Original line number Diff line number Diff line Loading @@ -34,12 +34,8 @@ class LocalEventTest { companion object { @JvmField @ClassRule(order = 0) val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)!! @JvmField @ClassRule(order = 1) val initCalendarProviderRule: TestRule = InitCalendarProviderRule() @ClassRule val initCalendarProviderRule: TestRule = InitCalendarProviderRule.getInstance() private val account = Account("LocalCalendarTest", ACCOUNT_TYPE_LOCAL) Loading Loading
app/src/androidTest/java/at/bitfire/davdroid/InitCalendarProviderRule.kt +58 −37 Original line number Diff line number Diff line Loading @@ -4,11 +4,15 @@ package at.bitfire.davdroid import android.Manifest import android.accounts.Account import android.content.ContentUris import android.content.ContentValues import android.os.Build import android.provider.CalendarContract import androidx.annotation.RequiresApi import androidx.test.platform.app.InstrumentationRegistry import androidx.test.rule.GrantPermissionRule import at.bitfire.davdroid.log.Logger import at.bitfire.davdroid.resource.LocalCalendar import at.bitfire.davdroid.resource.LocalEvent Loading @@ -16,29 +20,55 @@ import at.bitfire.ical4android.AndroidCalendar import at.bitfire.ical4android.Event import net.fortuna.ical4j.model.property.DtStart import net.fortuna.ical4j.model.property.RRule import org.junit.rules.RuleChain import org.junit.rules.TestRule import org.junit.runner.Description import org.junit.runners.model.Statement /** * JUnit ClassRule which initializes the AOSP CalendarProvider * Needed for some "flaky" tests which would otherwise only succeed on second run * JUnit ClassRule which initializes the AOSP CalendarProvider. * Needed for some "flaky" tests which would otherwise only succeed on second run. * * Currently tested on development machine (Ryzen) with Android 12 images (with/without Google Play). * Calendar provider behaves quite randomly, so it may or may not work. If you (the reader * if this comment) can find out on how to initialize the calendar provider so that the * tests are reliably run after `adb shell pm clear com.android.providers.calendar`, * please let us know! * * If you run tests manually, just make sure to ignore the first run after the calendar * provider has been accessed the first time. */ class InitCalendarProviderRule : TestRule { class InitCalendarProviderRule private constructor(): TestRule { companion object { private val account = Account("LocalCalendarTest", CalendarContract.ACCOUNT_TYPE_LOCAL) private val context = InstrumentationRegistry.getInstrumentation().targetContext private val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! private val uri = AndroidCalendar.create(account, provider, ContentValues()) private val calendar = AndroidCalendar.findByID(account, provider, LocalCalendar.Factory, ContentUris.parseId(uri)) fun getInstance() = RuleChain .outerRule(GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)) .around(InitCalendarProviderRule()) } override fun apply(base: Statement, description: Description): Statement { Logger.log.info("Before test: ${description.displayName}") Logger.log.info("Initializing calendar provider before running ${description.displayName}") return InitCalendarProviderStatement(base) } Logger.log.info("Initializing CalendarProvider (InitCalendarProviderRule)") class InitCalendarProviderStatement(val base: Statement): Statement() { override fun evaluate() { if (Build.VERSION.SDK_INT < 31) Logger.log.warning("Calendar provider initialization may or may not work. See InitCalendarProviderRule") initCalendarProvider() base.evaluate() } private fun initCalendarProvider() { val account = Account("LocalCalendarTest", CalendarContract.ACCOUNT_TYPE_LOCAL) val context = InstrumentationRegistry.getInstrumentation().targetContext val provider = context.contentResolver.acquireContentProviderClient(CalendarContract.AUTHORITY)!! val uri = AndroidCalendar.create(account, provider, ContentValues()) val calendar = AndroidCalendar.findByID(account, provider, LocalCalendar.Factory, ContentUris.parseId(uri)) try { // single event init val normalEvent = Event().apply { dtStart = DtStart("20220120T010203Z") Loading @@ -57,19 +87,10 @@ class InitCalendarProviderRule : TestRule { val localRecurringEvent = LocalEvent(calendar, recurringEvent, null, null, null, 0) localRecurringEvent.add() LocalEvent.numInstances(provider, account, localRecurringEvent.id!!) // Run test Logger.log.info("Evaluating test..") return try { object : Statement() { @Throws(Throwable::class) override fun evaluate() { base.evaluate() } } } finally { Logger.log.info("After test: $description") calendar.delete() } } } } No newline at end of file
app/src/androidTest/java/at/bitfire/davdroid/resource/LocalCalendarTest.kt +2 −6 Original line number Diff line number Diff line Loading @@ -31,12 +31,8 @@ class LocalCalendarTest { companion object { @JvmField @ClassRule(order = 0) val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)!! @JvmField @ClassRule(order = 1) val initCalendarProviderRule: TestRule = InitCalendarProviderRule() @ClassRule val initCalendarProviderRule: TestRule = InitCalendarProviderRule.getInstance() private lateinit var provider: ContentProviderClient Loading
app/src/androidTest/java/at/bitfire/davdroid/resource/LocalEventTest.kt +2 −6 Original line number Diff line number Diff line Loading @@ -34,12 +34,8 @@ class LocalEventTest { companion object { @JvmField @ClassRule(order = 0) val permissionRule = GrantPermissionRule.grant(Manifest.permission.READ_CALENDAR, Manifest.permission.WRITE_CALENDAR)!! @JvmField @ClassRule(order = 1) val initCalendarProviderRule: TestRule = InitCalendarProviderRule() @ClassRule val initCalendarProviderRule: TestRule = InitCalendarProviderRule.getInstance() private val account = Account("LocalCalendarTest", ACCOUNT_TYPE_LOCAL) Loading